From: Markus Triska Date: Fri, 28 Feb 2025 07:14:34 +0000 (+0100) Subject: correct handling of floats with N digits (~f and ~Nf) X-Git-Tag: v0.10.0~66^2~1 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=2d4fcf9714ac0b754446761a4c60278776c36657;p=scryer-prolog.git correct handling of floats with N digits (~f and ~Nf) This addresses #2771. Many thanks to @tmerr for reporting the issue! The code was posted by @UWN in: https://github.com/mthom/scryer-prolog/discussions/2805 Many thanks! With additional inputs by @adri326 and @notoria, who also posted interesting approaches which could help to increase precision in cases that are currently not ideally handled. Thank you all! Please see the issue and discussion for more information. --- diff --git a/src/lib/format.pl b/src/lib/format.pl index 96266c5d..63104519 100644 --- a/src/lib/format.pl +++ b/src/lib/format.pl @@ -285,36 +285,12 @@ cells([~|Fs0], Args0, Tab, Es, VNs) --> cells(Fs, Args, 0, [], VNs). cells([~,s|Fs], [Arg|Args], Tab, Es, VNs) --> !, cells(Fs, Args, Tab, [chars(Arg)|Es], VNs). -cells([~,f|Fs], [Arg|Args], Tab, Es, VNs) --> !, - { G = format_number_chars(Arg, Chars) }, - cells(Fs, Args, Tab, [chars(Chars),goal(G)|Es], VNs). +cells([~,f|Fs], Args, Tab, Es, VNs) --> !, + cells([~,'6',f|Fs], Args, Tab, Es, VNs). cells([~|Fs0], Args0, Tab, Es, VNs) --> { numeric_argument(Fs0, Num, [f|Fs], Args0, [Arg|Args]) }, !, - { G = (format_number_chars(Arg, Cs0), - phrase(upto_what(Bs, .), Cs0, Cs), - ( Num =:= 0 -> Chars = Bs - ; ( Cs = ['.'|Rest] -> - length(Rest, L), - ( Num < L -> - length(Ds, Num), - append(Ds, _, Rest) - ; Num =:= L -> - Ds = Rest - ; Num > L, - Delta is Num - L, - % we should look into the float with - % greater accuracy here, and use the - % actual digits instead of 0. - length(Zs, Delta), - maplist(=('0'), Zs), - append(Rest, Zs, Ds) - ) - ; length(Ds, Num), - maplist(=('0'), Ds) - ), - append(Bs, ['.'|Ds], Chars) - )) }, + { G = phrase(float_with_n_decimal_digits(Arg, Num), Chars) }, cells(Fs, Args, Tab, [chars(Chars),goal(G)|Es], VNs). cells([~,r|Fs], Args, Tab, Es, VNs) --> !, cells([~,'8',r|Fs], Args, Tab, Es, VNs). @@ -369,9 +345,18 @@ cells(Fs0, Args, Tab, Es, VNs) --> Fs1 = [_|_] }, cells(Fs, Args, Tab, [chars(Fs1)|Es], VNs). -format_number_chars(N0, Chars) :- - N is N0, % evaluate compound expression - number_chars(N, Chars). +float_with_n_decimal_digits(F, N) --> + { Fr is abs(float_fractional_part(F)), + FrR0 is round(Fr*10^N), + I0 is truncate(F), + ( FrR0 >= 10^N + -> I is I0+truncate(sign(F)), FrR = FrR0 + ; I = I0, FrR is FrR0+10^N + ) + }, + ( { I=0, F<0, FrR>10^N } -> "-0" ; { number_chars(I, Is) }, seq(Is) ), + ".", + ( { FrR = 1 } -> "0" ; { number_chars(FrR, ['1'|FrRs]) }, seq(FrRs) ). n_newlines(N0) --> { N0 > 0, N is N0 - 1 }, [newline], n_newlines(N). n_newlines(0) --> [].