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
Reply Hermann 1/28/2007 6:01:25 AM

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 
on your machine

Thanks, Hermann

0
Reply Hermann 1/28/2007 9:37:46 AM


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 
> on your machine

       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
Reply Janis 1/28/2007 10:02:20 AM

Janis Papanagnou wrote:
> Hermann wrote:
> 
>>
>> Any help is welcome. Perhaps you could give it a try with the printf 
>> on your machine
> 
> 
>       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
Reply Janis 1/28/2007 10:04:38 AM


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
> on your machine
>
> 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.
- Paddy.

0
Reply Paddy 1/28/2007 10:08:30 AM

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 
about that."
0
Reply Hermann 1/28/2007 11:24:00 AM

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 your problem.

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 
> about that."

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
Reply Janis 1/28/2007 12:40:50 PM

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.

> ...your problem.
> 

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
Reply Hermann 1/28/2007 2:13:38 PM

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
Reply cdl 1/30/2007 5:13:39 AM

Carl Lowenstein wrote:
> In article <45bc3c3e$0$71749$edfadb0f@dread11.news.tele.dk>,
> 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
Reply Hermann 1/30/2007 6:49:13 PM

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
Reply Steffen 2/1/2007 1:23:35 AM

One dull day if ever some lost imp scratched :

> Carl Lowenstein wrote:
>> In article <45bc3c3e$0$71749$edfadb0f@dread11.news.tele.dk>,
>> 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
Reply Alan 2/1/2007 7:53:01 PM

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
Reply Hermann 2/2/2007 6:54:55 AM

12 Replies
225 Views

(page loaded in 0.129 seconds)

Similiar Articles:


















7/27/2012 12:45:55 AM


Reply: