如何检查序言中每个数字的位置值?

发布于 2025-01-10 00:40:27 字数 386 浏览 1 评论 0原文

toword(0,'zero').
toword(1,'one').
toword(10,'ten').
toword(15,'fifteen').
toword(30,'thirty').
toword(100,'one hundred').
toword(500,'five hundred').
toword(2000,'two thousand).

pv(X,[]).
//pv(X , [H|T) :- toword(X/10, T), pv(???  I know this is wrong.

我试图获取每个位置的值并将其放入列表中。例如; X = 2531 列表将是 [2000,500,30,1]。我没有列出所有的 toword() 事实,但还会有更多。我不知道如何获得该数字的每个位值。

toword(0,'zero').
toword(1,'one').
toword(10,'ten').
toword(15,'fifteen').
toword(30,'thirty').
toword(100,'one hundred').
toword(500,'five hundred').
toword(2000,'two thousand).

pv(X,[]).
//pv(X , [H|T) :- toword(X/10, T), pv(???  I know this is wrong.

I am trying to get each place value and put it into a list. For example; X = 2531 the list would be [two thousand, five hundred, thirty, one]. I didn't put all of the toword() facts, but there would be more. I don't know how I am supposed to get each place value of the number.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

江湖正好 2025-01-17 00:40:27

将整数转换为其英语口语形式是一个比您想象的更困难的问题。

您需要做的第一件事是将您的值划分为 3 位数字组的列表(其正确名称是句点):

groups( 0 , Gs , Gs ) .
groups( N , Ts , Gs ) :- N > 0, div_rem(N,1000,Q,R), groups(Q,[R|Ts],Gs).

div_rem(X,Y,Q,R) :-
    Q is X div Y,
    R is X rem Y.

这将变成一个整数,例如 1234567890 像这样的东西

[ 1, 234, 567, 890 ]

会根据组相对于列表右侧的位置为您提供正确的后缀:

period( 2, thousand    ).
period( 3, million     ).
period( 4, billion     ).
period( 5, trillion    ).
period( 6, quadrillion ).
period( 7, quintillion ).
period( 8, sextillion  ).

唯一真正棘手的部分是弄清楚如何处理第一个/最右边的这样的句点 (数百)。 0-99 之间的数字是有问题的:

  • 值 0-19 是不规则的形式,
  • 值 20-99 是绝对规则的,并且由十年的名称组成(二十< /code>、三十等),附加一个-,然后在个位附加数字名称。

这些是特殊数字:

special(  0, zero       ).
special(  1, one        ).
special(  2, two        ).
special(  3, three      ).
special(  4, four       ).
special(  5, five       ).
special(  6, six        ).
special(  7, seven      ).
special(  8, eight      ).
special(  9, nine       ).
special( 10, ten        ).
special( 11, eleven     ).
special( 12, twelve     ).
special( 13, thirteen   ).
special( 14, fourteeen  ).
special( 15, fifteen    ).
special( 16, sixteen    ).
special( 17, seventeen  ). 
special( 18, eighteen   ).
special( 19, nineteen   ).
special( 20, twenty     ).
special( 30, thirty     ).
special( 40, forty      ).
special( 50, fifty      ).
special( 60, sixty      ).
special( 70, seventy    ).
special( 80, eighty     ).
special( 90, ninety     ).

以下是如何构造 0 到 999 之间的任何数字的名称:

group_name( 0 , Ws , Ws ) :- !.
group_name( N , Ws , W1 ) :-
    div_rem(N,100,Q,R),
    hundreds(Q,Ws,W0),
    tens_and_ones(R,W0,W1).
                 
hundreds( 0 , Ws              , Ws ).
hundreds( N ,  [W,hundred|W0] , W0 ) :- N > 0, special(N,W).

tens_and_ones( N ,     [W|Ws] , Ws ) :- special(N,W), !.
tens_and_ones( N , [W1-W2|Ws] , Ws ) :-
    Ones is N rem 10,
    Tens is N - Ones,
    special(Tens,W1),
    special(Ones,W2).

一旦有了这个名称,其他一切就很容易了。这只是跟踪您当前正在处理的时间段并附加正确的后缀的问题

int_words( N , _             ) :- \+ integer(N), !, fail.
int_words( N , [negative|Ws] ) :- N <  0, X is abs(N), number_phrase(X,Ws).
int_words( N ,           Ws  ) :- N >= 0,              number_phrase(N,Ws).

number_phrase(N,Ws) :-
    groups(N,[],Gs),
    length(Gs,P),
    groups_to_words(Gs,P,Ws).

groups_to_words( [G]    , _ , Ws ) :-
    group_name(G,Ws,[]).
groups_to_words( [G|Gs] , P , Ws ) :-
    period(P,Sfx),
    group_name(G,Ws,[Sfx|W1]),
    P1 is P-1,
    groups_to_words(Gs,P1,W1).

您可以在 https://swish.swi-prolog.org/p/int-words.pl

Converting an integer into its English language spoken form is rather a more difficult problem than you might think.

You first thing you need to do is partition your value into a list of 3-digit groups (the proper name for which is period):

groups( 0 , Gs , Gs ) .
groups( N , Ts , Gs ) :- N > 0, div_rem(N,1000,Q,R), groups(Q,[R|Ts],Gs).

div_rem(X,Y,Q,R) :-
    Q is X div Y,
    R is X rem Y.

That will turn an integer like 1234567890 into

[ 1, 234, 567, 890 ]

Something like this will give you the correct suffix based on the groups position with respect to the right of the list:

period( 2, thousand    ).
period( 3, million     ).
period( 4, billion     ).
period( 5, trillion    ).
period( 6, quadrillion ).
period( 7, quintillion ).
period( 8, sextillion  ).

The only real tricky bit is figuring out how to handle the 1st/rightmost such period (hundreds). The numbers from 0-99 are problematic:

  • The values 0-19 are an irregular formation,
  • The values 20-99 are absolutely regular, and formed by taking the name of the decade (twenty, thirty, etc.), appending a - and then appending the name of the digit in the ones place.

These are the special numbers:

special(  0, zero       ).
special(  1, one        ).
special(  2, two        ).
special(  3, three      ).
special(  4, four       ).
special(  5, five       ).
special(  6, six        ).
special(  7, seven      ).
special(  8, eight      ).
special(  9, nine       ).
special( 10, ten        ).
special( 11, eleven     ).
special( 12, twelve     ).
special( 13, thirteen   ).
special( 14, fourteeen  ).
special( 15, fifteen    ).
special( 16, sixteen    ).
special( 17, seventeen  ). 
special( 18, eighteen   ).
special( 19, nineteen   ).
special( 20, twenty     ).
special( 30, thirty     ).
special( 40, forty      ).
special( 50, fifty      ).
special( 60, sixty      ).
special( 70, seventy    ).
special( 80, eighty     ).
special( 90, ninety     ).

Here's how to construct the names of any number from 0-999:

group_name( 0 , Ws , Ws ) :- !.
group_name( N , Ws , W1 ) :-
    div_rem(N,100,Q,R),
    hundreds(Q,Ws,W0),
    tens_and_ones(R,W0,W1).
                 
hundreds( 0 , Ws              , Ws ).
hundreds( N ,  [W,hundred|W0] , W0 ) :- N > 0, special(N,W).

tens_and_ones( N ,     [W|Ws] , Ws ) :- special(N,W), !.
tens_and_ones( N , [W1-W2|Ws] , Ws ) :-
    Ones is N rem 10,
    Tens is N - Ones,
    special(Tens,W1),
    special(Ones,W2).

Once you have that, everything else is easy. It's just a matter of tracking which period you're currently processing and appending the correct suffix

int_words( N , _             ) :- \+ integer(N), !, fail.
int_words( N , [negative|Ws] ) :- N <  0, X is abs(N), number_phrase(X,Ws).
int_words( N ,           Ws  ) :- N >= 0,              number_phrase(N,Ws).

number_phrase(N,Ws) :-
    groups(N,[],Gs),
    length(Gs,P),
    groups_to_words(Gs,P,Ws).

groups_to_words( [G]    , _ , Ws ) :-
    group_name(G,Ws,[]).
groups_to_words( [G|Gs] , P , Ws ) :-
    period(P,Sfx),
    group_name(G,Ws,[Sfx|W1]),
    P1 is P-1,
    groups_to_words(Gs,P1,W1).

You can fiddle with it at https://swish.swi-prolog.org/p/int-words.pl

瑶笙 2025-01-17 00:40:27
toword(0, 'zero').
toword(1, 'one').
toword(10, 'ten').
toword(15, 'fifteen').
toword(30, 'thirty').
toword(100, 'one hundred').
toword(500, 'five hundred').
toword(2000, 'two thousand').

to_words(N, Lst) :-
    to_words_(N, Lst).

to_words_(N, Lst) :-
    % Using compare, to prevent unwanted choicepoint
    compare(Comp, N, 0),
    to_words_comp_(Comp, N, Lst).

to_words_comp_(=, 0, []).
to_words_comp_(>, N, [Text|Lst]) :-
    toword_min(N, TextN, Text),
    N0 is N - TextN,
    % Loop until zero is reached
    to_words_(N0, Lst).

toword_min(N, TextN, Text) :-
    toword(TextN, Text),
    TextN =< N,
    % Ensure this is the most fitting number to use
    \+ (toword(TextNOther, _), TextNOther =< N, TextNOther > TextN),
    % No need to search for multiple answers
    !.

swi-prolog 中的结果:

?- time(to_words(2531, Lst)).
% 286 inferences, 0.000 CPU in 0.000 seconds (97% CPU, 1656013 Lips)
Lst = ['two thousand','five hundred',thirty,one].
toword(0, 'zero').
toword(1, 'one').
toword(10, 'ten').
toword(15, 'fifteen').
toword(30, 'thirty').
toword(100, 'one hundred').
toword(500, 'five hundred').
toword(2000, 'two thousand').

to_words(N, Lst) :-
    to_words_(N, Lst).

to_words_(N, Lst) :-
    % Using compare, to prevent unwanted choicepoint
    compare(Comp, N, 0),
    to_words_comp_(Comp, N, Lst).

to_words_comp_(=, 0, []).
to_words_comp_(>, N, [Text|Lst]) :-
    toword_min(N, TextN, Text),
    N0 is N - TextN,
    % Loop until zero is reached
    to_words_(N0, Lst).

toword_min(N, TextN, Text) :-
    toword(TextN, Text),
    TextN =< N,
    % Ensure this is the most fitting number to use
    \+ (toword(TextNOther, _), TextNOther =< N, TextNOther > TextN),
    % No need to search for multiple answers
    !.

Result in swi-prolog:

?- time(to_words(2531, Lst)).
% 286 inferences, 0.000 CPU in 0.000 seconds (97% CPU, 1656013 Lips)
Lst = ['two thousand','five hundred',thirty,one].
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文