Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #165576 > unrolled thread

Re: Adjusting printf() rounding

Started byJames Kuyper <jameskuyper@alumni.caltech.edu>
First post2022-04-08 12:15 -0400
Last post2022-04-09 20:51 -0700
Articles 3 — 3 participants

Back to article view | Back to comp.lang.c

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: Adjusting printf() rounding James Kuyper <jameskuyper@alumni.caltech.edu> - 2022-04-08 12:15 -0400
    Re: Adjusting printf() rounding Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-04-09 09:28 -0700
      Re: Adjusting printf() rounding "james...@alumni.caltech.edu" <jameskuyper@alumni.caltech.edu> - 2022-04-09 20:51 -0700

#165576 — Re: Adjusting printf() rounding

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2022-04-08 12:15 -0400
SubjectRe: Adjusting printf() rounding
Message-ID<t2pn31$jkc$1@dont-email.me>
On 4/8/22 08:40, Paavo Helde wrote:
>
> To be honest, this is a bit off-topic for C++, but maybe you guys have
> some insight here.
>
> This is an excerpt from
> "https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/printf-printf-l-wprintf-wprintf-l?view=msvc-170"
>
> "Starting in Windows 10 version 2004 (build 19041), the printf family
> of functions prints exactly representable floating point numbers
> according to the IEEE 754 rules for rounding. In previous versions of
> Windows, exactly representable floating point numbers ending in '5'
> would always round up. IEEE 754 states that they must round to the
> closest even digit (also known as "Banker's Rounding"). For example,
> both printf("%1.0f", 1.5) and printf("%1.0f", 2.5) should round to 2.
> Previously, 1.5 would round to 2 and 2.5 would round to 3. [...] This
> change only affects programs built using Visual Studio 2019 version
> 16.2 and later."
>
> glibc has similar page and similar rules, though they do not speak
> about printf or iostream directly:
> "https://www.gnu.org/software/libc/manual/html_node/Rounding.html"
>
> I can understand that rounding-to-even rule is good in mathematical
> operations as it is statistically unbiased. However, with printf the
> rounding appears in decimal, not in binary, and the result is meant
> primarily for human consumption, not for statistics. It is not clear
> to me these things should follow the same ideology, what do you think?
>
> What's worse, it appears MSVC have not kept the promises which they
> made, and have reverted back to pre-MSVC19 behavior in VS2019 Update
> 11 (_MSC_VER==1929), rounding ties now up again.
>
> For me this means we have nasty cross-platform differences which we
> would rather try to avoid. How could we coerce glibc() to round up, or
> failing that, coerce MSVC to round down? I was thinking about adding
> or subtracting one ULP to the number beforehand, but this would surely
> ruin some other outputs (in my program I have no control over the
> numbers or precisions, these come from outside).
>
> A demo program:
>
> $ cat test6.cpp
> #include <cstdio>
> int main() {
> std::printf("%.3g\n", 212.5);
> }
> $ g++ test6.cpp
> $ ./a.out
> 212

I know nothing MSVC-specific, but I can tell you what the C standard
requires:

When printing floating point numbers, the *printf*() family is supposed
to obey the current rounding direction.

<fenv.h> defines macros for rounding directions. A given macro is
defined if and only if the implementation supports that rounding
direction. The standard describes 5 rounding modes, implementations are
allowed to add to that list.

#pragma STDC FENV_ROUND

May be used to set the rounding direction. One option is FE_DYNAMIC,
which allows the rounding direction to be changed by calls to
fesetround(). Be sure to check the return value from fesetround() - it's
not required to succeed.

If this worries you, it might be a good idea to use one of the new
decimal floating point types: _Decimal32, _Decimal64, or _Decimal128, if
your implementation supports them. The decimal floating point types have
their own equivalents of all the rounding direction features I described
above. The decimal floating point rounding direction need not be the
same as the regular floating point types.

[toc] | [next] | [standalone]


#165594

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2022-04-09 09:28 -0700
Message-ID<86ilri9q6q.fsf@linuxsc.com>
In reply to#165576
James Kuyper <jameskuyper@alumni.caltech.edu> writes:

> On 4/8/22 08:40, Paavo Helde wrote:
>
>> To be honest, this is a bit off-topic for C++, but maybe you guys
>> have some insight here.
>>
>> [.. behavior of rounding on floating-point output ..]
>>
>> A demo program:
>>
>> $ cat test6.cpp
>> #include <cstdio>
>> int main() {
>> std::printf("%.3g\n", 212.5);
>> }
>> $ g++ test6.cpp
>> $ ./a.out
>> 212
>
> I know nothing MSVC-specific, but I can tell you what the C
> standard requires:
>
> When printing floating point numbers, the *printf*() family is
> supposed to obey the current rounding direction.
> [.. discussion of rounding modes and how to set them ..]

I believe this assertion is an overstatement.  Although there are
certain cases where the C standard does mandate correct rounding
(which implies using the current rounding direction), AFAICT
there is no general requirement that all *printf() floating-point
conversions be correctly rounded, or that they obey the current
rounding direction.  Note that some statements are made about
rounding (both correct rounding and current rounding direction)
under a "Recommended practice" heading, but these statements are
only recommendations, not requirements.

[toc] | [prev] | [next] | [standalone]


#165595

From"james...@alumni.caltech.edu" <jameskuyper@alumni.caltech.edu>
Date2022-04-09 20:51 -0700
Message-ID<61a0874c-6851-400d-bd03-9ba116801c75n@googlegroups.com>
In reply to#165594
On Saturday, April 9, 2022 at 12:28:43 PM UTC-4, Tim Rentsch wrote:
> James Kuyper <james...@alumni.caltech.edu> writes: 
> 
> > On 4/8/22 08:40, Paavo Helde wrote: 
> > 
> >> To be honest, this is a bit off-topic for C++, but maybe you guys 
> >> have some insight here. 
> >>
> >> [.. behavior of rounding on floating-point output ..]
> >> 
> >> A demo program: 
> >> 
> >> $ cat test6.cpp 
> >> #include <cstdio> 
> >> int main() { 
> >> std::printf("%.3g\n", 212.5); 
> >> } 
> >> $ g++ test6.cpp 
> >> $ ./a.out 
> >> 212 
> > 
> > I know nothing MSVC-specific, but I can tell you what the C 
> > standard requires: 
> > 
> > When printing floating point numbers, the *printf*() family is 
> > supposed to obey the current rounding direction.
> > [.. discussion of rounding modes and how to set them ..] 
> 
> I believe this assertion is an overstatement. Although there are 
> certain cases where the C standard does mandate correct rounding 
> (which implies using the current rounding direction), AFAICT 
> there is no general requirement that all *printf() floating-point 
> conversions be correctly rounded,

That is quite correct. 
"The accuracy of the floating-point operations ( + , - , * , / ) and of the
library functions in <math.h> and <complex.h> that return floating-
point results is implementation-defined, as is the accuracy of the
conversion between floating-point internal representations and
string representations performed by the library functions in
<stdio.h> , <stdlib.h> , and <wchar.h> . The implementation may
state that the accuracy is unknown." (5.2.2.4.2p8).

As a result of what the standard fails to mandate about the
accuracy of floating point operations, a fully conforming
implementation need not implement floating point in any useful
fashion. In particular, a conforming implementation of 
printf("%g", LDBL_MAX) could perform the conversion between
internal and string representations so inaccurately that the result
would be -LDBL_MAX, so long as it's documentation says that it's
that inaccurate, or even merely says "the accuracy is unknown".

> ... or that they obey the current 
> rounding direction. Note that some statements are made about 
> rounding (both correct rounding and current rounding direction) 
> under a "Recommended practice" heading, but these statements are 
> only recommendations, not requirements.

That's why I used "supposed" rather than "required".

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web