COMPGROUPS.NET | Search | Post Question | Groups | Stream | About | Register

### A printf and rounding question

• Follow

```Dear All,

As I know from own experience and from the AWK manual, I have to be
careful with printf's rounding logic:

---snip---
12.2.4 Rounding Numbers
The way printf and sprintf (see Printf) perform rounding often depends
upon the system's C sprintf subroutine. On many machines, sprintf
rounding is �unbiased,� which means it doesn't always round a trailing
`.5' up, contrary to naive expectations.
---snip---

http://www.gnu.org/software/gawk/manual/gawk.html#Round-Function

My question is now: can someone help me to understand my own printf's
rounding logic, which is not normal=biased=round-5-up, nor
unbiased=round-5-to-even, nor round-5-to-odd (always talking about the
trailing 5 in the fraction). The results are just confusing, at least to
me, see below.

\$ printf "%.3f\n" 3.5115
3.511

\$ printf "%.3f\n" 3.5125
3.513

\$ printf "%.3f\n" 3.5135
3.514

\$ printf "%.3f\n" 3.5145
3.514

\$ printf "%.3f\n" 3.5155
3.515

\$ printf "%.3f\n" 3.5165
3.517

\$ printf "%.3f\n" 3.5175
3.518

\$ printf "%.3f\n" 3.5185
3.518

\$ printf "%.3f\n" 3.5195
3.519

Or is this all some Cygwin hokus-pokus?

\$ cat /proc/version
CYGWIN_NT-5.1 1.5.21(0.156/4/2) 2006-07-30 14:21

Or is it perhaps related to the more generic problem that computers with
their binary logic have some (more or less predictable) difficulties
with floating-point numbers from the decimal system?
see e.g. at: http://docs.sun.com/source/806-3568/ncg_goldberg.html

Thanks, Hermann
```
 0

```On Jan 28, 7:01 am, Hermann Peifer <pei...@gmx.net> wrote:
>
> \$ printf "%.3f\n" 3.5115
> 3.511
>
> \$ printf "%.3f\n" 3.5125
> 3.513
>
> \$ printf "%.3f\n" 3.5135
> 3.514
>
> \$ printf "%.3f\n" 3.5145
> 3.514
>
> \$ printf "%.3f\n" 3.5155
> 3.515
>
> \$ printf "%.3f\n" 3.5165
> 3.517
>
> \$ printf "%.3f\n" 3.5175
> 3.518
>
> \$ printf "%.3f\n" 3.5185
> 3.518
>
> \$ printf "%.3f\n" 3.5195
> 3.519
>
> Or is this all some Cygwin hokus-pokus?
>
> \$ cat /proc/version
> CYGWIN_NT-5.1 1.5.21(0.156/4/2) 2006-07-30 14:21
>
>Or is it perhaps related to the more generic problem that computers with
> their binary logic have some (more or less predictable) difficulties
> with floating-point numbers from the decimal system?
> see e.g. at: http://docs.sun.com/source/806-3568/ncg_goldberg.html

Now I am really puzzled:

peifer@zorro:~> printf "%.3f\n" 3.5105
3.511
peifer@zorro:~> printf "%.3f\n" 3.5115
3.512
peifer@zorro:~> printf "%.3f\n" 3.5125
3.513
peifer@zorro:~> printf "%.3f\n" 3.5135
3.514
peifer@zorro:~> printf "%.3f\n" 3.5145
3.515
peifer@zorro:~> printf "%.3f\n" 3.5155
3.516
peifer@zorro:~> printf "%.3f\n" 3.5165
3.516
peifer@zorro:~> printf "%.3f\n" 3.5175
3.517
peifer@zorro:~> printf "%.3f\n" 3.5185
3.518
peifer@zorro:~> printf "%.3f\n" 3.5195
3.519

peifer@zorro:~> cat /proc/version
Linux version 2.6.13-15.7-default (geeko@buildhost) (gcc version 4.0.2
20050901 (prerelease) (SUSE Linux)) #1 Tue Nov 29 14:32:29 UTC 2005
peifer@zorro:~>

Any help is welcome. Perhaps you could give it a try with the printf

Thanks, Hermann

```
 0

```Hermann wrote:
> On Jan 28, 7:01 am, Hermann Peifer <pei...@gmx.net> wrote:
>
>>\$ printf "%.3f\n" 3.5115
>>3.511
>>
>>\$ printf "%.3f\n" 3.5125
>>3.513
>>
>>\$ printf "%.3f\n" 3.5135
>>3.514
>>
>>\$ printf "%.3f\n" 3.5145
>>3.514
>>
>>\$ printf "%.3f\n" 3.5155
>>3.515
>>
>>\$ printf "%.3f\n" 3.5165
>>3.517
>>
>>\$ printf "%.3f\n" 3.5175
>>3.518
>>
>>\$ printf "%.3f\n" 3.5185
>>3.518
>>
>>\$ printf "%.3f\n" 3.5195
>>3.519
>>
>>Or is this all some Cygwin hokus-pokus?
>>
>>\$ cat /proc/version
>>CYGWIN_NT-5.1 1.5.21(0.156/4/2) 2006-07-30 14:21
>>
>>Or is it perhaps related to the more generic problem that computers with
>>their binary logic have some (more or less predictable) difficulties
>>with floating-point numbers from the decimal system?
>>see e.g. at: http://docs.sun.com/source/806-3568/ncg_goldberg.html
>
>
>
> Now I am really puzzled:
>
> peifer@zorro:~> printf "%.3f\n" 3.5105
> 3.511
> peifer@zorro:~> printf "%.3f\n" 3.5115
> 3.512
> peifer@zorro:~> printf "%.3f\n" 3.5125
> 3.513
> peifer@zorro:~> printf "%.3f\n" 3.5135
> 3.514
> peifer@zorro:~> printf "%.3f\n" 3.5145
> 3.515
> peifer@zorro:~> printf "%.3f\n" 3.5155
> 3.516
> peifer@zorro:~> printf "%.3f\n" 3.5165
> 3.516
> peifer@zorro:~> printf "%.3f\n" 3.5175
> 3.517
> peifer@zorro:~> printf "%.3f\n" 3.5185
> 3.518
> peifer@zorro:~> printf "%.3f\n" 3.5195
> 3.519
>
> peifer@zorro:~> cat /proc/version
> Linux version 2.6.13-15.7-default (geeko@buildhost) (gcc version 4.0.2
> 20050901 (prerelease) (SUSE Linux)) #1 Tue Nov 29 14:32:29 UTC 2005
> peifer@zorro:~>
>
> Any help is welcome. Perhaps you could give it a try with the printf

ksh     zsh    bash    gawk
3.510   3.510   3.511   3.51
3.511   3.511   3.512   3.511
3.513   3.513   3.513   3.513
3.514   3.514   3.514   3.514
3.514   3.514   3.515   3.514
3.515   3.515   3.516   3.515
3.517   3.517   3.516   3.517
3.518   3.518   3.517   3.518
3.518   3.518   3.518   3.518
3.519   3.519   3.519   3.519

Calling printf() from C matches the awk results.

ksh 1993-12-28 r
zsh 4.0.6
GNU bash, version 2.05b.0(1)
GNU Awk 3.1.1

>
> Thanks, Hermann
>
```
 0

```Janis Papanagnou wrote:
> Hermann wrote:
>
>>
>> Any help is welcome. Perhaps you could give it a try with the printf
>
>
>       ksh     zsh    bash    gawk
>     3.510   3.510   3.511   3.51
>     3.511   3.511   3.512   3.511
>     3.513   3.513   3.513   3.513
>     3.514   3.514   3.514   3.514
>     3.514   3.514   3.515   3.514
>     3.515   3.515   3.516   3.515
>     3.517   3.517   3.516   3.517
>     3.518   3.518   3.517   3.518
>     3.518   3.518   3.518   3.518
>     3.519   3.519   3.519   3.519
>
> Calling printf() from C matches the awk results.
>
> ksh 1993-12-28 r
> zsh 4.0.6

zsh's printf actually is /usr/bin/printf
ksh's and bash's are built-in.

> GNU bash, version 2.05b.0(1)
> GNU Awk 3.1.1
>
>>
>> Thanks, Hermann
>>
```
 0

```
On Jan 28, 9:37 am, "Hermann" <pei...@gmx.net> wrote:
> On Jan 28, 7:01 am, Hermann Peifer <pei...@gmx.net> wrote:
>
>
>
>
>
> > \$ printf "%.3f\n" 3.5115
> > 3.511
>
> > \$ printf "%.3f\n" 3.5125
> > 3.513
>
> > \$ printf "%.3f\n" 3.5135
> > 3.514
>
> > \$ printf "%.3f\n" 3.5145
> > 3.514
>
> > \$ printf "%.3f\n" 3.5155
> > 3.515
>
> > \$ printf "%.3f\n" 3.5165
> > 3.517
>
> > \$ printf "%.3f\n" 3.5175
> > 3.518
>
> > \$ printf "%.3f\n" 3.5185
> > 3.518
>
> > \$ printf "%.3f\n" 3.5195
> > 3.519
>
> > Or is this all some Cygwin hokus-pokus?
>
> > \$ cat /proc/version
> > CYGWIN_NT-5.1 1.5.21(0.156/4/2) 2006-07-30 14:21
>
> >Or is it perhaps related to the more generic problem that computers with
> > their binary logic have some (more or less predictable) difficulties
> > with floating-point numbers from the decimal system?
> > see e.g. at:http://docs.sun.com/source/806-3568/ncg_goldberg.htmlNow I am really puzzled:
>
> peifer@zorro:~> printf "%.3f\n" 3.5105
> 3.511
> peifer@zorro:~> printf "%.3f\n" 3.5115
> 3.512
> peifer@zorro:~> printf "%.3f\n" 3.5125
> 3.513
> peifer@zorro:~> printf "%.3f\n" 3.5135
> 3.514
> peifer@zorro:~> printf "%.3f\n" 3.5145
> 3.515
> peifer@zorro:~> printf "%.3f\n" 3.5155
> 3.516
> peifer@zorro:~> printf "%.3f\n" 3.5165
> 3.516
> peifer@zorro:~> printf "%.3f\n" 3.5175
> 3.517
> peifer@zorro:~> printf "%.3f\n" 3.5185
> 3.518
> peifer@zorro:~> printf "%.3f\n" 3.5195
> 3.519
>
> peifer@zorro:~> cat /proc/version
> Linux version 2.6.13-15.7-default (geeko@buildhost) (gcc version 4.0.2
> 20050901 (prerelease) (SUSE Linux)) #1 Tue Nov 29 14:32:29 UTC 2005
> peifer@zorro:~>
>
> Any help is welcome. Perhaps you could give it a try with the printf
>
> Thanks, Hermann
It could be due to the internal representation of the floating point
numer sometimes being above or beow what you think. Try printing %.33f
or something.

```
 0

```Janis Papanagnou wrote:
>
>       ksh     zsh    bash    gawk
>     3.510   3.510   3.511   3.51
>     3.511   3.511   3.512   3.511
>     3.513   3.513   3.513   3.513
>     3.514   3.514   3.514   3.514
>     3.514   3.514   3.515   3.514
>     3.515   3.515   3.516   3.515
>     3.517   3.517   3.516   3.517
>     3.518   3.518   3.517   3.518
>     3.518   3.518   3.518   3.518
>     3.519   3.519   3.519   3.519
>
> Calling printf() from C matches the awk results.
>
> ksh 1993-12-28 r
> zsh 4.0.6
> GNU bash, version 2.05b.0(1)
> GNU Awk 3.1.1
>

Thanks indeed, although I am getting even more puzzled.

This basically tells me that it is time now to open another thread in
this group on how to expand the round.awk function from the GAWK manual,
correct?

One of my thoughts in a previous posting was that some of the issues
behind the (somewhat) unpredictable results can be avoided when
splitting the floating point number into the 2 parts, as the fractional
part would become an integer this way. Is this thought reasonable?

Hermann

PS
On this Sunday morning, my 10-year-old son is sitting next to me on
another PC, playing World of Warcraft. I asked him what he knows about
rounding, in particular about cases with a trailing 5. "Why? A trailing
5 is always rounded up", he said. "Everyone in our 4th grade class knows
```
 0

```Hermann Peifer wrote:
>
> Thanks indeed, although I am getting even more puzzled.
>
> This basically tells me that it is time now to open another thread in
> this group on how to expand the round.awk function from the GAWK manual,
> correct?
>
> One of my thoughts in a previous posting was that some of the issues
> behind the (somewhat) unpredictable results can be avoided when
> splitting the floating point number into the 2 parts, as the fractional
> part would become an integer this way. Is this thought reasonable?

Hmm.., maybe. I am usure whether awk will read and store data that matches
a numerical value as a string or whether it will already convert it to a
FP number thus suffering from the inherent conversion inaccuracies. But at
least you may try that approach.

{ split(\$0,fp,"[,.]"); print fp[1], fp[2] }

will give you the two parts and using the length and substr function may

Janis

>
> Hermann
>
> PS
> On this Sunday morning, my 10-year-old son is sitting next to me on
> another PC, playing World of Warcraft. I asked him what he knows about
> rounding, in particular about cases with a trailing 5. "Why? A trailing
> 5 is always rounded up", he said. "Everyone in our 4th grade class knows

At that time I also "knew" that. But mind, mathematics is not computer
science.

Mathematics may be hard, but to make things really disgusting you need
a computer. (I read something along that line a couple of years ago.)
```
 0

```Janis Papanagnou wrote:
> Hermann Peifer wrote:
>>
>> Thanks indeed, although I am getting even more puzzled.
>>
>> This basically tells me that it is time now to open another thread in
>> this group on how to expand the round.awk function from the GAWK
>> manual, correct?
>>
>> One of my thoughts in a previous posting was that some of the issues
>> behind the (somewhat) unpredictable results can be avoided when
>> splitting the floating point number into the 2 parts, as the
>> fractional part would become an integer this way. Is this thought
>> reasonable?
>
> Hmm.., maybe. I am usure whether awk will read and store data that matches
> a numerical value as a string or whether it will already convert it to a
> FP number thus suffering from the inherent conversion inaccuracies. But at
> least you may try that approach.
>
>   { split(\$0,fp,"[,.]"); print fp[1], fp[2] }
>
> will give you the two parts and using the length and substr function may solve...

Thanks for the hint.

>

I still have some vague hope that this rounding issue is not only *my*
problem. It should be a known issue (which someone has already solved
years ago by writing the AWK function I am looking for).

As it is only a rounding, but not a burning issue ;-) I will wait
another day or two. Perhaps someone will point me in the right direction.

Hermann
```
 0

```In article <45bc3c3e\$0\$71749\$edfadb0f@dread11.news.tele.dk>,
Hermann Peifer  <peifer@gmx.net> wrote:
>Dear All,
>
>As I know from own experience and from the AWK manual, I have to be
>careful with printf's rounding logic:
>
>My question is now: can someone help me to understand my own printf's
>rounding logic, which is not normal=biased=round-5-up, nor
>unbiased=round-5-to-even, nor round-5-to-odd (always talking about the
>trailing 5 in the fraction). The results are just confusing, at least to
>me, see below.
>
>\$ printf "%.3f\n" 3.5115
>3.511
>
>\$ printf "%.3f\n" 3.5125
>3.513
>
>\$ printf "%.3f\n" 3.5135
>3.514
>
>\$ printf "%.3f\n" 3.5145
>3.514
>
>
>Or is it perhaps related to the more generic problem that computers with
>their binary logic have some (more or less predictable) difficulties
>with floating-point numbers from the decimal system?
>see e.g. at: http://docs.sun.com/source/806-3568/ncg_goldberg.html

It is precisely related to the fact that an "exact" decimal fraction
can almost never be expressed exactly as a binary floating-point number.
So when you write 3.5135 the computer will express it as either 117893496
* 2^-25 or 117893497 * 2^-25.  One of these values is slightly less than
3.5135, the other is slightly greater.  Similarly, the round-off value of
0.0005 to be added to this will have some binary approximation which is
not exactly equal to 0.0005.  And the sum will be a binary number that
you will then have to find the nearest decimal approximation to.

Kernighan and Plauger:
"Floating point numbers are like piles of sand; every time you move
one you lose a little sand and pick up a little dirt."

carl
--
carl lowenstein         marine physical lab     u.c. san diego
clowenst@ucsd.edu
```
 0

```Carl Lowenstein wrote:
> Hermann Peifer  <peifer@gmx.net> wrote:
>>
>>
>> Or is it perhaps related to the more generic problem that computers with
>> their binary logic have some (more or less predictable) difficulties
>> with floating-point numbers from the decimal system?
>> see e.g. at: http://docs.sun.com/source/806-3568/ncg_goldberg.html
>
> It is precisely related to the fact that an "exact" decimal fraction
> can almost never be expressed exactly as a binary floating-point number.
> So when you write 3.5135 the computer will express it as either 117893496
> * 2^-25 or 117893497 * 2^-25.  One of these values is slightly less than
> 3.5135, the other is slightly greater.  Similarly, the round-off value of
> 0.0005 to be added to this will have some binary approximation which is
> not exactly equal to 0.0005.  And the sum will be a binary number that
> you will then have to find the nearest decimal approximation to.
>
> Kernighan and Plauger:
>   "Floating point numbers are like piles of sand; every time you move
>   one you lose a little sand and pick up a little dirt."
>
>     carl

Thanks for the explanation and the quote.

In principle, I was aware of the problems with binary floating-point
numbers. I did however believe that this would only affect computer
scientists doing some mega-calculations on their super-computers and not
me with my trivial rounding of small numbers.

Now I know better.

Hermann
```
 0

```Hermann Peifer wrote:
> Dear All,
>
> As I know from own experience and from the AWK manual, I have to be
> careful with printf's rounding logic:
>
> ---snip---
> 12.2.4 Rounding Numbers
> The way printf and sprintf (see Printf) perform rounding often depends
> upon the system's C sprintf subroutine. On many machines, sprintf
> rounding is �unbiased,� which means it doesn't always round a trailing
> `.5' up, contrary to naive expectations.
> ---snip---
>
> http://www.gnu.org/software/gawk/manual/gawk.html#Round-Function
>
> My question is now: can someone help me to understand my own printf's
> rounding logic, which is not normal=biased=round-5-up, nor
> unbiased=round-5-to-even, nor round-5-to-odd (always talking about the
> trailing 5 in the fraction). The results are just confusing, at least to
> me, see below.
>
> \$ printf "%.3f\n" 3.5115
> 3.511
>
> \$ printf "%.3f\n" 3.5125
> 3.513
>
> \$ printf "%.3f\n" 3.5135
> 3.514
>
> \$ printf "%.3f\n" 3.5145
> 3.514
>
> \$ printf "%.3f\n" 3.5155
> 3.515
>
> \$ printf "%.3f\n" 3.5165
> 3.517
>
> \$ printf "%.3f\n" 3.5175
> 3.518
>
> \$ printf "%.3f\n" 3.5185
> 3.518
>
> \$ printf "%.3f\n" 3.5195
> 3.519
>
> Or is this all some Cygwin hokus-pokus?
>
> \$ cat /proc/version
> CYGWIN_NT-5.1 1.5.21(0.156/4/2) 2006-07-30 14:21
>
> Or is it perhaps related to the more generic problem that computers with
> their binary logic have some (more or less predictable) difficulties
> with floating-point numbers from the decimal system?
> see e.g. at: http://docs.sun.com/source/806-3568/ncg_goldberg.html
>
> Thanks, Hermann

A good document to the floating point arithmetic:

http://docs.sun.com/source/806-3568/ncg_goldberg.html

Enjoy,

Steffen
```
 0

```One dull day if ever some lost imp scratched :

> Carl Lowenstein wrote:
>> Hermann Peifer  <peifer@gmx.net> wrote:
>>>
>>>
>>> Or is it perhaps related to the more generic problem that computers with
>>> their binary logic have some (more or less predictable) difficulties
>>> with floating-point numbers from the decimal system?
>>> see e.g. at: http://docs.sun.com/source/806-3568/ncg_goldberg.html
>>
>> It is precisely related to the fact that an "exact" decimal fraction
>> can almost never be expressed exactly as a binary floating-point number.
>> So when you write 3.5135 the computer will express it as either 117893496
>> * 2^-25 or 117893497 * 2^-25.  One of these values is slightly less than
....
>> Kernighan and Plauger:
>>   "Floating point numbers are like piles of sand; every time you move
>>   one you lose a little sand and pick up a little dirt."
....
> Thanks for the explanation and the quote.
>
> In principle, I was aware of the problems with binary floating-point
> numbers. I did however believe that this would only affect computer
> scientists doing some mega-calculations on their super-computers and not
> me with my trivial rounding of small numbers.

Well, you should know there is no such thing as a small number :-)
Especially when the value of 0 is growing up to 1.

> Now I know better.

And you also know that 'trivial' is not necessarily
synonym to 'easy', nor to  'simple' ;-)
```
 0

```On Feb 1, 1:23 am, Steffen Schuler <schuler.steffenDELETE_T...@gmx.de>
wrote:
> Hermann Peifer wrote:
> > Or is it perhaps related to the more generic problem that computers with
> > their binary logic have some (more or less predictable) difficulties
> > with floating-point numbers from the decimal system?
> > see e.g. at:http://docs.sun.com/source/806-3568/ncg_goldberg.html  <---
>
> > Thanks, Hermann
>
> A good document to the floating point arithmetic:
>
> http://docs.sun.com/source/806-3568/ncg_goldberg.html   <---
>
> Enjoy,
>
> Steffen

I assume you did not read the last lines of my article before replying
-- or do I miss the joke?

Puzzled, Hermann

```
 0

12 Replies
225 Views

Similiar Articles:

7/27/2012 12:45:55 AM