Re: Division in C++

henry@spsystems.net (Henry Spencer)
12 Jul 2005 05:15:09 -0400

          From comp.compilers

Related articles
Division in C++ garms@gmx.de (Onno Garms) (2005-07-11)
Re: Division in C++ antounk@comcast.net (Antoun Kanawati) (2005-07-12)
Re: Division in C++ qrczak@knm.org.pl (Marcin 'Qrczak' Kowalczyk) (2005-07-12)
Re: Division in C++ tmk@netvision.net.il (Michael Tiomkin) (2005-07-12)
Re: Division in C++ henry@spsystems.net (2005-07-12)
Re: Division in C++ fw@deneb.enyo.de (Florian Weimer) (2005-07-12)
Re: Division in C++ gdr@integrable-solutions.net (Gabriel Dos Reis) (2005-07-12)
Re: Division in C++ qrczak@knm.org.pl (Marcin 'Qrczak' Kowalczyk) (2005-07-12)
Re: Division in C++ garms@gmx.de (Onno Garms) (2005-07-17)
Re: Division in C++ poenitz@htwm.de (Andre Poenitz) (2005-08-10)
| List of all articles for this month |

From: henry@spsystems.net (Henry Spencer)
Newsgroups: comp.compilers,gnu.g++.help
Date: 12 Jul 2005 05:15:09 -0400
Organization: SP Systems, Toronto, Canada
References: 05-07-046
Keywords: arithmetic, C++
Posted-Date: 12 Jul 2005 05:15:09 EDT

In article 05-07-046, Onno Garms <garms@gmx.de> wrote:
>What I want the program to do in the loop is the following:
>1. compute a/b
>2. compute a/b again
>3. compare to previous result
>4. see that it is the same and break the loop
>However the program runs in an endless loop.


Almost certainly, what is happening here is that `a/b' is being
computed in extended precision -- normally a good thing to do, and
actually somewhat hard to avoid in the x86 floating-point architecture
-- and is being rounded to `double' when you assign it to the
variable. So no, the computed value of `a/b' is *not* quite the same
as the value assigned to the variable, so it is not surprising that
you get an infinite loop. When you do the comparison, the variable
value is being converted back to extended precision and compared to
the extended-precision result of the division, rather than the
extended-precision result being rounded to the precision of the
variable and then compared.


Try declaring `c' as `long double' instead. That might (depending on
the compiler) get you an extended-precision variable.


Floating-point computation unfortunately is full of subtleties like this.
Doing equality comparisons on floating-point values is almost never a
good idea.


>Regardless of any rounding errors, a/b should always return
>the same value, shouldn't it?


Yes... until it gets rounded to a lower precision to store it in a
variable.


>- Finally, the program below prints "not yet" (and nothing else):
> while (1)
> {
> c = a/b;
> if ((d=a/b)<=c) break;
> std::cout << "not yet\n";
> if (d<=c) break;
> std::cout << "but now\n";
> }


Now *this* is arguably a compiler bug. I would guess that in the first
comparison, the compiler is storing the value in `d' -- rounding it to
`double' in the process -- but is then using the old extended-precision
value still in the register for the comparison. That's possibly faster
than reloading the value from the variable, but it's not really right:
the value of the parenthesized subexpression is supposed to be the value
of the variable.
--
"Think outside the box -- the box isn't our friend." | Henry Spencer
                                                                -- George Herbert | henry@spsystems.net


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.