1. sprintf usage with %d gives a rounding problem

For a Euro conversion of a financial bank-statements interface file, I 
have to put an integer value into strings sequence in order to output 
this to an Ascci flatfile record.

The length of the string value is max. 18 characters, therefore I use an 
atom variable instead of an integer declaration.

For the integer_to_string conversion I use the sprintf(%d,a) function
This works OK for most of the times, but today we ran into a problem 
that the following value (displayed by the exw interpreter debugger)gets 
the wrong result. By the way: the value of atom a is the result of the 
sum of several bank-statements.

Value a = 9200616 (according the exw debugger screen)
the result of the 
   sa = sprintf("%d",a)
gives the value in the sequence of "9200615" and this should be 
"9200616"

Looking further into the situation, I noticed that real value of a is 
9200615.9999999963

So it looks like, that the %d does not round to the value 9200616.

You can understand that this an awkward situation.

Nevertheless I solved this with a workaround, but what can be the 
reason?
Any suggestions are most welcome.

By the way: for the performance SIG people: we choose euphoria for a 
production job in splitting up a large address file (>200MB, about 
950,000 records) into smaller parts. A small benchkmark of reading the 
file and compare each record for a certain string showed the following 
results:
Euphoria   17 secs
Perl5      57 secs
Python    156 secs
The final processing is done in about 2.5 minutes running on a notebook 
with W98(Intel 600Mc, 256MB internal mem.)


Jan Willem Teunisse
Amersfoort
The Netherlands

new topic     » topic index » view message » categorize

2. Re: sprintf usage with %d gives a rounding problem

Jan Willem Teunisse writes:
> Value a = 9200616 (according the exw debugger screen)
> the result of the 
>   sa = sprintf("%d",a)
> gives the value in the sequence of "9200615" 
> and this should be "9200616"
> Looking further into the situation, I noticed that 
> real value of a is 9200615.9999999963

The debugger rounds numbers. 
"%d" truncates.
If you want rounding, try "%.0f" - print a floating-point number
with zero decimal places.

If you are doing currency calculations,
be aware that numbers like 0.1 and 0.01 are
not stored exactly using binary floating-point hardware.
For instance 0.1 + 0.1 +0.1 ... (ten times) ... != 1.0
Be prepared to get results that end in .99999999
rather than .000000000

Regards,
   Rob Craig
   Rapid Deployment Software
   http://www.RapidEuphoria.com

new topic     » goto parent     » topic index » view message » categorize

3. Re: sprintf usage with %d gives a rounding problem

On 15 Feb 2001, at 10:00, Jan Willem Teunisse wrote:

> For a Euro conversion of a financial bank-statements interface file, I 
> have to put an integer value into strings sequence in order to output 
> this to an Ascci flatfile record.
> 
> The length of the string value is max. 18 characters, therefore I use an 
> atom variable instead of an integer declaration.
> 
> For the integer_to_string conversion I use the sprintf(%d,a) function
> This works OK for most of the times, but today we ran into a problem 
> that the following value (displayed by the exw interpreter debugger)gets 
> the wrong result. By the way: the value of atom a is the result of the 
> sum of several bank-statements.
> 
> Value a = 9200616 (according the exw debugger screen)
> the result of the 
>    sa = sprintf("%d",a)
> gives the value in the sequence of "9200615" and this should be 
> "9200616"
> 
> Looking further into the situation, I noticed that real value of a is 
> 9200615.9999999963

This will always be a problem in doing math on binary puters, sorry to say.
Human
deal in decimal math, puters deal in binary math, and the two do not translate
well. I
suggest, for accuracy and reliability, you use string math. Basically speaking,
all the
operands are strings (so they can be any size and accuracy) which you parse, and
perform math on with a lookup table of results. If you have multiply("5","5"),
you look
up multiply[5][5] and get "25" which you apply appropriately. I don't know if
there are
any Eu routines for this yet, but i have seen some Perl routines. Warning:
string math
is incredibly slow, but you cannot beat the accuracy (and number of significant
digits),
it's been used to calculate pi out to thousands of decimal points. Possibly you
can
use string math only in multiplication and division, and use regular integer
math for
addition and multiplication. Or use repeated addition for multiplication, and a
subtract
loop for division.

Kat

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu