From: cziwkga AT ulcc DOT ac DOT uk (Kevin Ashley) Newsgroups: comp.os.msdos.djgpp Subject: Re: double-->int: What's wrong here? Date: 6 Feb 1997 18:16:12 GMT Organization: University of London Computer Centre Lines: 54 Distribution: world Message-ID: <5dd75c$1g3@calypso.ulcc.ac.uk> References: <32f887b7 DOT 44544 AT news-win DOT inp DOT nsk DOT su> Reply-To: k DOT ashley AT ulcc DOT ac DOT uk NNTP-Posting-Host: silver-e.ulcc.ac.uk To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp In article <32f887b7 DOT 44544 AT news-win DOT inp DOT nsk DOT su>, myskin AT inp DOT nsk DOT su (Vyacheslav O. Myskin) writes: |>Hi everybody! |> |>Please explain me what is wrong with this: |> |>------------------------------------------------------------------ |>#include |> |>int main() |> { |> double d1,d2; |> int n1,n2; |> |> d1=1./4300.; |> n1=(int)(.05/d1); |> d2=.05/d1; |> n2=(int)d2; |> printf("n1=%d n2=%d d2=%f\n",n1,n2,d2); |> return 0; |> } |>------------------------------------------------------------------- |>Compiled with DJGPP 2.01, options: -O0 -g -Wall |> |>The output is: |>n1=214 n2=215 d2=215.000000 |> |>So why n1 is not equal to n2? Very short answer: Rounding Not so short: Just because two expressions are algebraically equivalent doesn't mean that they will give the same answer. In fact, even the same expression can validly return different answers at different times if anything other than integer or logical operations are involved. Fuller answer: The calculation is highly numerically unstable. A change of 1 in the 15th significant digit of (1./4300.) makes the second computation equal either 215.0000000 or 214.999999999. The computation of n1 does the calculation using 80 bit floats, and then gets the FPU to convert the 80 bit result to integer internally, before storing the result. This yields the (presumably more accurate) 214.999999... as the floating point number, which gets truncated to 214 using the float->int conversion rules. n2, however, is computed using the 64-bit result stored in d2, which is slightly less accurate than the original 80-bit value. That one digit difference in the 15th significant digit turns 214.99999... into 215.000000. If you depend on this, use rounding rather than truncation when converting float/double to int (ie. n1 = (int)((double expression)+0.5)), but this still doesn't really resolve the problem. ----------------------------------------------------------------------------- Kevin Ashley K DOT Ashley AT Ulcc DOT ac DOT uk Development Manager http://www.ulcc.ac.uk/staff/Kevin+Ashley University of London Computer Centre. ...ukc!ncdlab!K.Ashley This is not a signature