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


Groups > comp.lang.c++ > #83528 > unrolled thread

Adjusting printf() rounding

Started byPaavo Helde <eesnimi@osa.pri.ee>
First post2022-04-08 15:40 +0300
Last post2022-04-09 09:10 -0700
Articles 18 — 10 participants

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


Contents

  Adjusting printf() rounding Paavo Helde <eesnimi@osa.pri.ee> - 2022-04-08 15:40 +0300
    Re: Adjusting printf() rounding Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2022-04-08 06:02 -0700
    Re: Adjusting printf() rounding Marcel Mueller <news.5.maazl@spamgourmet.org> - 2022-04-08 18:21 +0200
      Re: Adjusting printf() rounding Paavo Helde <eesnimi@osa.pri.ee> - 2022-04-08 19:38 +0300
        Re: Adjusting printf() rounding Sams Lara <samlara622@gmail.com> - 2022-04-08 18:48 +0100
          Re: Adjusting printf() rounding Paavo Helde <eesnimi@osa.pri.ee> - 2022-04-08 23:44 +0300
            Re: Adjusting printf() rounding Marcel Mueller <news.5.maazl@spamgourmet.org> - 2022-04-09 12:58 +0200
              Re: Adjusting printf() rounding Geoff <geoff@invalid.invalid> - 2022-04-09 08:45 -0700
              Re: Adjusting printf() rounding Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-04-09 13:05 -0700
                Re: Adjusting printf() rounding red floyd <no.spam.here@its.invalid> - 2022-04-09 13:36 -0700
              Re: Adjusting printf() rounding Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-09 16:08 -0700
    Re: Adjusting printf() rounding Manfred <noname@add.invalid> - 2022-04-08 21:30 +0200
    Re: Adjusting printf() rounding "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2022-04-09 10:11 +0200
      Re: Adjusting printf() rounding Paavo Helde <eesnimi@osa.pri.ee> - 2022-04-10 16:39 +0300
        Re: Adjusting printf() rounding Sams Lara <samlara622@gmail.com> - 2022-04-10 18:36 +0100
          Re: Adjusting printf() rounding Paavo Helde <eesnimi@osa.pri.ee> - 2022-04-10 21:50 +0300
    Re: Adjusting printf() rounding Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-09 09:05 -0700
      Re: Adjusting printf() rounding Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-04-09 09:10 -0700

#83528 — Adjusting printf() rounding

FromPaavo Helde <eesnimi@osa.pri.ee>
Date2022-04-08 15:40 +0300
SubjectAdjusting printf() rounding
Message-ID<t2pag0$eab$1@dont-email.me>
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




TIA
Paavo

[toc] | [next] | [standalone]


#83529

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2022-04-08 06:02 -0700
Message-ID<e6a0708c-30ac-4d4a-b91f-4423b715c280n@googlegroups.com>
In reply to#83528
On Friday, 8 April 2022 at 13:40:47 UTC+1, 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). 
> 
printf() is used a lot for learner programs, and for debugging. There the results of
a floating point conversion are probably intended for human reading.
However in real production use, it's unlikely you'd want to display many floating
point number for humans to read. The output would mostly go for automatic
processing at a later stage. An example is paths in SVG files - these are
text, but they are primarily intended for parsers to read.

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


#83536

FromMarcel Mueller <news.5.maazl@spamgourmet.org>
Date2022-04-08 18:21 +0200
Message-ID<t2pnek$3f5em$1@gwaiyur.mb-net.net>
In reply to#83528
Am 08.04.22 um 14:40 schrieb Paavo Helde:
> I can understand that rounding-to-even rule is good in mathematical 
> operations as it is statistically unbiased.

... if the values are evenly distributed.

> However, with printf the 
> rounding appears in decimal, not in binary, and the result is meant 

There is no difference between decimal and binary representation with 
respect to rounding to integers since both number systems share the same 
prime factor 2. This also applies if you use fractional numbers because 
this is equivalent to a multiplication with a power of ten followed by 
an integer rounding.
And if you run out of sufficient binary digits this typically happened 
before the rounding.

> primarily for human consumption, not for statistics. It is not clear to 
> me these things should follow the same ideology, what do you think?

For deterministic results floating point types are not appropriate. 
Applications that depend on this are broken by design.
Whoever depends on deterministic fractional numbers should use decimal 
floats or fixed point numbers.

> 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?

Why should you care about that difference?

If you have more complex calculations with floating point numbers not 
only the last digit is indeterminate. E.g. transcendental functions 
typically do not provide the maximum possible precision in many FPU 
implementations.

And if you depend on a specific rounding mode you should use your own 
rounding with round/floor/ceil which have well defined behavior.


Marcel

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


#83537

FromPaavo Helde <eesnimi@osa.pri.ee>
Date2022-04-08 19:38 +0300
Message-ID<t2podd$ubk$1@dont-email.me>
In reply to#83536
08.04.2022 19:21 Marcel Mueller kirjutas:

>> 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?
> 
> Why should you care about that difference?
> 
> If you have more complex calculations with floating point numbers not 
> only the last digit is indeterminate. E.g. transcendental functions 
> typically do not provide the maximum possible precision in many FPU 
> implementations.
> 
> And if you depend on a specific rounding mode you should use your own 
> rounding with round/floor/ceil which have well defined behavior.

I'm not concerned about the last (16-th) digit at all. In this case, I'm 
concerned about the third digit.

printf("%.3g\n", 212.5) yields 212 in Linux and 213 on Windows.

Even if we could swallow it ourselves, it would be hard to explain our 
customers why our software works inconsistently cross platform.

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


#83539

FromSams Lara <samlara622@gmail.com>
Date2022-04-08 18:48 +0100
Message-ID<t2psnc$19rm$1@gioia.aioe.org>
In reply to#83537
On 08/04/2022 17:38, Paavo Helde wrote:
>
> I'm not concerned about the last (16-th) digit at all. In this case, 
> I'm concerned about the third digit.
>
> printf("%.3g\n", 212.5) yields 212 in Linux and 213 on Windows.
>
> Even if we could swallow it ourselves, it would be hard to explain our 
> customers why our software works inconsistently cross platform.

I am getting 212 on Windows 11 as well 64 bit:

#include <stdio.h>

int main(void)
{
    printf("%0.3g\n", 212.5);
    printf("%0.3g\n", 213.5);
    printf("%0.3g\n", 214.5);
    printf("%0.3g\n", 215.5);

    return 0;

    /* Output in Windows 11 using Visual Studio 2022
    212
    214
    214
    216
    */
}

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


#83542

FromPaavo Helde <eesnimi@osa.pri.ee>
Date2022-04-08 23:44 +0300
Message-ID<t2q6rp$kgd$1@dont-email.me>
In reply to#83539
08.04.2022 20:48 Sams Lara kirjutas:
> On 08/04/2022 17:38, Paavo Helde wrote:
>>
>> I'm not concerned about the last (16-th) digit at all. In this case, 
>> I'm concerned about the third digit.
>>
>> printf("%.3g\n", 212.5) yields 212 in Linux and 213 on Windows.
>>
>> Even if we could swallow it ourselves, it would be hard to explain our 
>> customers why our software works inconsistently cross platform.
> 
> I am getting 212 on Windows 11 as well 64 bit:
> 
> #include <stdio.h>
> 
> int main(void)
> {
>     printf("%0.3g\n", 212.5);
>     printf("%0.3g\n", 213.5);
>     printf("%0.3g\n", 214.5);
>     printf("%0.3g\n", 215.5);
> 
>     return 0;
> 
>     /* Output in Windows 11 using Visual Studio 2022
>     212
>     214
>     214
>     216
>     */
> }

Yes, you are right, it looks like Windows/MSVC is in principle also 
switching over to Banker's Rounding, but it seems there are some 
combinations of OS and the MSVC compiler where this has not yet 
happened. Probably I just need to give up and forget about the problem, 
it will sort itself out in some years.

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


#83545

FromMarcel Mueller <news.5.maazl@spamgourmet.org>
Date2022-04-09 12:58 +0200
Message-ID<t2ros9$3mkhv$1@gwaiyur.mb-net.net>
In reply to#83542
Am 08.04.22 um 22:44 schrieb Paavo Helde:
> Yes, you are right, it looks like Windows/MSVC is in principle also 
> switching over to Banker's Rounding, but it seems there are some 
> combinations of OS and the MSVC compiler where this has not yet 
> happened.

The OS is probably not significant. The related code should be in in the 
C runtime, i.e. msvcrt*.dll. So basically it depends on the MSVC version.

> Probably I just need to give up and forget about the problem, 
> it will sort itself out in some years.

Or you just use another compiler. If your software is cross platform it 
should be straight forward to use e.g. gcc (or mingw) on Windows which 
will very likely behave the same as on other platforms since they all 
share the same glibc code.


Marcel

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


#83549

FromGeoff <geoff@invalid.invalid>
Date2022-04-09 08:45 -0700
Message-ID<gaa35h9b1tv4cd82gudk3l4h9eqttt7klj@4ax.com>
In reply to#83545
On Sat, 9 Apr 2022 12:58:17 +0200, Marcel Mueller
<news.5.maazl@spamgourmet.org> wrote:

>Am 08.04.22 um 22:44 schrieb Paavo Helde:
>> Yes, you are right, it looks like Windows/MSVC is in principle also 
>> switching over to Banker's Rounding, but it seems there are some 
>> combinations of OS and the MSVC compiler where this has not yet 
>> happened.
>
>The OS is probably not significant. The related code should be in in the 
>C runtime, i.e. msvcrt*.dll. So basically it depends on the MSVC version.
>
>> Probably I just need to give up and forget about the problem, 
>> it will sort itself out in some years.
>
>Or you just use another compiler. If your software is cross platform it 
>should be straight forward to use e.g. gcc (or mingw) on Windows which 
>will very likely behave the same as on other platforms since they all 
>share the same glibc code.
>
>
>Marcel

Per the Microsoft Runtime Library Reference:
"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 exactly representable numbers. For example, 2.35 (which,
when represented in memory, is closer to 2.35000000000000008)
continues to round up to 2.4. Rounding done by these functions now
also respects the floating point rounding mode set by fesetround.
Previously, rounding always chose FE_TONEAREST behavior. This change
only affects programs built using Visual Studio 2019 version 16.2 and
later. To use the legacy floating point rounding behavior, link with
legacy_stdio_float_rounding.obj."

So, yes, it was OS-dependent but implemented in the MSVCRT library
supplied with Windows 10.

It's also very explicit about what you need to do to stop this
behavior.

https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/printf-printf-l-wprintf-wprintf-l?f1url=%3FappId%3DDev16IDEF1%26l%3DEN-US%26k%3Dk(STDIO%252Fprintf);k(printf);k(DevLang-C%252B%252B);k(TargetOS-Windows)%26rd%3Dtrue&view=msvc-170

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


#83550

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2022-04-09 13:05 -0700
Message-ID<87ilrinhss.fsf@nosuchdomain.example.com>
In reply to#83545
Marcel Mueller <news.5.maazl@spamgourmet.org> writes:
> Am 08.04.22 um 22:44 schrieb Paavo Helde:
>> Yes, you are right, it looks like Windows/MSVC is in principle also
>> switching over to Banker's Rounding, but it seems there are some 
>> combinations of OS and the MSVC compiler where this has not yet
>> happened.
>
> The OS is probably not significant. The related code should be in in
> the C runtime, i.e. msvcrt*.dll. So basically it depends on the MSVC
> version.

msvcrt.dll is used only by old versions of Microsoft Visual C++, from
4.2 to 6.0.  More modern versions of MS Visual Studio use different
DLLs.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

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


#83551

Fromred floyd <no.spam.here@its.invalid>
Date2022-04-09 13:36 -0700
Message-ID<t2sqpb$9li$1@redfloyd.dont-email.me>
In reply to#83550
On 4/9/2022 1:05 PM, Keith Thompson wrote:
> Marcel Mueller <news.5.maazl@spamgourmet.org> writes:
>> Am 08.04.22 um 22:44 schrieb Paavo Helde:
>>> Yes, you are right, it looks like Windows/MSVC is in principle also
>>> switching over to Banker's Rounding, but it seems there are some
>>> combinations of OS and the MSVC compiler where this has not yet
>>> happened.
>>
>> The OS is probably not significant. The related code should be in in
>> the C runtime, i.e. msvcrt*.dll. So basically it depends on the MSVC
>> version.
> 
> msvcrt.dll is used only by old versions of Microsoft Visual C++, from
> 4.2 to 6.0.  More modern versions of MS Visual Studio use different
> DLLs.
> 

Here's the details.

https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=msvc-170

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


#83552

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2022-04-09 16:08 -0700
Message-ID<t2t3kv$aue$1@dont-email.me>
In reply to#83545
On 4/9/2022 3:58 AM, Marcel Mueller wrote:
> Am 08.04.22 um 22:44 schrieb Paavo Helde:
>> Yes, you are right, it looks like Windows/MSVC is in principle also 
>> switching over to Banker's Rounding, but it seems there are some 
>> combinations of OS and the MSVC compiler where this has not yet happened.
> 
> The OS is probably not significant. The related code should be in in the 
> C runtime, i.e. msvcrt*.dll. So basically it depends on the MSVC version.
> 

It is true that the OS itself is not significant. But starting from some 
past version of MSVC the run-time library has been detached from the 
MSVC package and became part of an independently-installed and 
independently-updated WindowsSDK package. One can say that WindowsSDK is 
arguably closer associated with OS than with MSVC.

-- 
Best regards,
Andrey Tarasevich

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


#83541

FromManfred <noname@add.invalid>
Date2022-04-08 21:30 +0200
Message-ID<t2q2ge$1vn6$1@gioia.aioe.org>
In reply to#83528
On 4/8/2022 2:40 PM, 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 few suggestions:

1) implement your own rounding routine.

2) use static linking - the dependency on Windows version (Windows 10 
version 2004 as you mention) means a dependency on the version of one of 
the successors of msvcrt.dll. You should get rid of this runtime 
dependency by linking in the static C runtime library. This means that 
if your application is linked with the Banker's version of the runtime 
it should use that rounding on any Windows version. Cross-consistency 
between Linux and Windows might be trickier, though.

3) depending on the nature of data, this might be just optics:
If it's data representing physical quantities, then 2.5 might just as 
well come in as 2.4999999999 or 2.5000000001, and the chance of getting 
exactly 2.5 is negligible, while on the other hand rounded numbers are 
grossly inexact by definition.
If it's data where 2.5 has some significant probability (e.g. monetary 
quantities) then probably even option 1 is easy enough.

HTH.

> 
> A demo program:
> 
> $ cat test6.cpp
> #include <cstdio>
> int main() {
>      std::printf("%.3g\n", 212.5);
> }
> $ g++ test6.cpp
> $ ./a.out
> 212
> 
> 
> 
> 
> TIA
> Paavo

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


#83543

From"Alf P. Steinbach" <alf.p.steinbach@gmail.com>
Date2022-04-09 10:11 +0200
Message-ID<t2rf2n$gmj$1@dont-email.me>
In reply to#83528
On 8 Apr 2022 14: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
> 
> 
> 
> 
> TIA
> Paavo

I haven't used Dragonbox but apparently you can specify the rounding 
policy, so you could write something on top that has the default you 
want -- or just use the default round-to-even on all systems.

https://github.com/jk-jeon/dragonbox

- Alf

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


#83561

FromPaavo Helde <eesnimi@osa.pri.ee>
Date2022-04-10 16:39 +0300
Message-ID<t2umn3$suj$1@dont-email.me>
In reply to#83543
09.04.2022 11:11 Alf P. Steinbach kirjutas:
> 
> I haven't used Dragonbox but apparently you can specify the rounding 
> policy, so you could write something on top that has the default you 
> want -- or just use the default round-to-even on all systems.
> 
> https://github.com/jk-jeon/dragonbox

Thanks for the reply, it appears indeed the best approach is to use an 
alternative library like Dragonbox or Google's double_conversion.

These libraries also have the advantage of not depending on the locale, 
making them both faster and more robust than the standard sprintf().

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


#83562

FromSams Lara <samlara622@gmail.com>
Date2022-04-10 18:36 +0100
Message-ID<t2v4q5$1srj$1@gioia.aioe.org>
In reply to#83561
On 10/04/2022 14:39, Paavo Helde wrote:
>
> Thanks for the reply, it appears indeed the best approach is to use an 
> alternative library like Dragonbox or Google's double_conversion.
>
> These libraries also have the advantage of not depending on the 
> locale, making them both faster and more robust than the standard 
> sprintf().


I think the best approach is to use this small function:

float RoundCustom(float ValueToRound)
{
	return (floorf(ValueToRound + 0.5));
}


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


#83564

FromPaavo Helde <eesnimi@osa.pri.ee>
Date2022-04-10 21:50 +0300
Message-ID<t2v8u1$ica$1@dont-email.me>
In reply to#83562
10.04.2022 20:36 Sams Lara kirjutas:
> On 10/04/2022 14:39, Paavo Helde wrote:
>>
>> Thanks for the reply, it appears indeed the best approach is to use an 
>> alternative library like Dragonbox or Google's double_conversion.
>>
>> These libraries also have the advantage of not depending on the 
>> locale, making them both faster and more robust than the standard 
>> sprintf().
> 
> 
> I think the best approach is to use this small function:
> 
> float RoundCustom(float ValueToRound)
> {
>      return (floorf(ValueToRound + 0.5));
> }

Sure, this would work fine if my task would be rounding to integers.

Unfortunately, it's not (rather, it is about implementing an equivalent 
of sprintf() in a cross-platform interpreted script language).

Cheers
Paavo

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


#83546

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2022-04-09 09:05 -0700
Message-ID<t2sarf$7g9$1@dont-email.me>
In reply to#83528
On 4/8/2022 5:40 AM, Paavo Helde wrote:
> 
> 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.
> 

Technically, it is no longer a promise of MSVC, but rather a promise of 
Windows SDK. However, it is run-time controllable through such internal 
SDK options as

   _CRT_INTERNAL_PRINTF_STANDARD_ROUNDING

and apparently different versions of MSVC set different initial settings 
in the program's startup code, since the same version of SDK produces 
different results in different versions of MSVC.

   #include <cstdio>
   int main()
   {
     std::printf("%.3g\n", 212.5);

     *__local_stdio_printf_options() |=
        _CRT_INTERNAL_PRINTF_STANDARD_ROUNDING;

     std::printf("%.3g\n", 212.5);

     *__local_stdio_printf_options() &=
       ~_CRT_INTERNAL_PRINTF_STANDARD_ROUNDING;

     std::printf("%.3g\n", 212.5);
   }

Visual Studio 2017

   213
   212
   213

Visual Studio 2019

   212
   212
   213

-- 
Best regards,
Andrey Tarasevich

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


#83547

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2022-04-09 09:10 -0700
Message-ID<t2sb6d$as9$1@dont-email.me>
In reply to#83546
On 4/9/2022 9:05 AM, Andrey Tarasevich wrote:
> On 4/8/2022 5:40 AM, Paavo Helde wrote:
>>
>> 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.
>>
> 
> Technically, it is no longer a promise of MSVC, but rather a promise of 
> Windows SDK. However, it is run-time controllable through such internal 
> SDK options as
> 
>    _CRT_INTERNAL_PRINTF_STANDARD_ROUNDING
> 
> and apparently different versions of MSVC set different initial settings 
> in the program's startup code, since the same version of SDK produces 
> different results in different versions of MSVC.
> 

Also, once you enable

   _CRT_INTERNAL_PRINTF_STANDARD_ROUNDING

`printf` in MSVC begins to obey the rounding modes set by `fesetround`

   #include <cstdio>
   #include <cfenv>

   int main()
   {
     *__local_stdio_printf_options() |=
       _CRT_INTERNAL_PRINTF_STANDARD_ROUNDING;

     std::printf("%.3g\n", 212.5);

     std::fesetround(FE_UPWARD);
     std::printf("%.3g\n", 212.5);

     std::fesetround(FE_DOWNWARD);
     std::printf("%.3g\n", 212.5);

     std::fesetround(FE_TONEAREST);
     std::printf("%.3g\n", 212.5);
   }

   212
   213
   212
   212

-- 
Best regards,
Andrey Tarasevich

[toc] | [prev] | [standalone]


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


csiph-web