469,913 Members | 2,352 Online

double trouble

I have a not-so-large double in the range 1-1000, but with fractional
part. I only do ++my_double to increment it, however sometimes it
happens that after incrementing

int(old_double) == int(new_double)

why? Again the doubles are not large at all, their exponents cannot be
so high to shift out the 1 I add out when incrementing and we have 64
bits to use here.
Feb 23 '07 #1
5 1766 On Feb 23, 12:08 pm, John Doe <NOTOSPAMjohndoe64...@yahoo.comwrote:
I have a not-so-large double in the range 1-1000, but with fractional
part. I only do ++my_double to increment it, however sometimes it
happens that after incrementing

int(old_double) == int(new_double)

why? Again the doubles are not large at all, their exponents cannot be
so high to shift out the 1 I add out when incrementing and we have 64
bits to use here.
It's kind of hard to know without some code sample
that shows the behaviour. But it's just possible that
the ++ operation took you from <number that is so close
to integer N that it is indistinguishable to the int()>
to <number that is very close to N+1, but just enough
smaller that it is distinguishable to int()>.

I'm guessing that you are working with numbers that are
quite close to integer values.

Don't forget that doubles are stored in a floating point
format. It may be that you have found one of those spots
where you can't perfectly represent a real number as a
floating point. You may think you've got a slightly
smaller number for the old than you really do, and
you may think you've got a slightly larger value for
the new than you really do.

Generally speaking, you should be doing a different kind
of compare, if you really must compare floating point
values. You should be defining some kind of tolerance
for equality, then checking if the difference is less
than this tolerance. And you should be aware of such
issues as loss of accuracy due to subtracting numbers
that are very close to eachother.
Socks

Feb 23 '07 #2
John Doe wrote:
I have a not-so-large double in the range 1-1000, but with fractional
part. I only do ++my_double to increment it, however sometimes it
happens that after incrementing

int(old_double) == int(new_double)

why? Again the doubles are not large at all, their exponents cannot be
so high to shift out the 1 I add out when incrementing and we have 64
bits to use here.
First of all, a nit pick: you most likely only have 53 bits, not 64.
Second, can you provide a concrete example? And how do you know that
int(before) == int(after)? By looking at it in the debugger? The
only case I know where it would be true if the double in on (-1,0) to
begin with.

V
--
Feb 23 '07 #3
John Doe wrote:
I have a not-so-large double in the range 1-1000, but with fractional
part. I only do ++my_double to increment it, however sometimes it
happens that after incrementing

int(old_double) == int(new_double)

why? Again the doubles are not large at all, their exponents cannot be
so high to shift out the 1 I add out when incrementing and we have 64
bits to use here.
Casting to int truncates the fractional part. Some values do
not have a finite representation in binary format and so cannot
be stored in a double with infinite accuracy. I imagine the
scenario is something like (though not for number 42):

double x=42; // actually becomes x=42.00000000000001
int y=(int)x; // the fractional part is truncated, y becomes 42.
x++; // actually becomes x=42.99999999999999
int z=(int)x; // the fractional part is truncated, z becomes 42.
z==y; // true

... but this is just guessing.

HTH,
- J.
Feb 23 '07 #4
Jacek Dziedzic wrote:
John Doe wrote:
>I have a not-so-large double in the range 1-1000, but with fractional
part. I only do ++my_double to increment it, however sometimes it
happens that after incrementing

int(old_double) == int(new_double)

why? Again the doubles are not large at all, their exponents cannot
be so high to shift out the 1 I add out when incrementing and we
have 64 bits to use here.

Casting to int truncates the fractional part. Some values do
not have a finite representation in binary format and so cannot
be stored in a double with infinite accuracy. I imagine the
scenario is something like (though not for number 42):

double x=42; // actually becomes x=42.00000000000001
That is very unlikely. Integers of this magnitude are represented
precisely in IEEE floats. It could be after some kind of imprecise
calcuation, of course.
int y=(int)x; // the fractional part is truncated, y becomes 42.
x++; // actually becomes x=42.99999999999999
That is not possible. How can adding 1 screw up the mantissa so
int z=(int)x; // the fractional part is truncated, z becomes 42.
z==y; // true

... but this is just guessing.
Yep.

What's going on with the number when you add 1?

Before adding the FP number can be written (in binary form) as

1bbbbbb.bbbbbbbbbbbbbB (total of N binary digits)
^^^^^^^
K digits before binary point. 'B' is the last binary digit
in the representation.

After adding 1 we could have either

10000000.bbbbbbbbbbbbbb (total of N binary digits)
^^^^^^^
K zeros

which would mean the last digit ('B') is lost or rounded to make
the fraction slightly different. If it's rounded "down", it is
the same as throwing it out. If it's rounded up, you can end up
with a fraction that when rounded eventually turns into another 1
and is added to the integral part (for that you need the fractional
part full of 1s). In either case adding 1 cannot mean retaining
the integral part (it either grows by 1 or by 2).

We could have (after adding 1)

1bbbbbb.bbbbbbbbbbbbbB (total of N binary digits)
^^^^^^^
K (slightly different) digits before binary point. 'B' is
still the last binary digit, in which case the fraction does not
change at all, and simply cannot contribute to changing the
integral part.

V
--
Feb 23 '07 #5
You were right c++ wizards:

x started low ~-1e-14, adding 1 to this produced, 0.something very close
to 1, but int(old_double) == int(new_double). Then there was additional
trouble: adding 1 to this repeatedly was producing numbers very close to
round(x) integers and then suddenly adding 1 rounded a
number_close_to_an_integer upwards and 1 integer was skipped by int(x),

511.99999999999999999999

int() would produce 511, but if you'd add 1 to this and hence shifted it
right sufficient places, you might produce 513, instead of
512.99999999999999999999.

Anyway, std::round(x) solved my problem, thank you.
Feb 23 '07 #6

 10 posts views Thread by Jacek Dziedzic | last post: by 10 posts views Thread by Robert Palma | last post: by 67 posts views Thread by lcw1964 | last post: by 11 posts views Thread by Ole Nielsby | last post: by 4 posts views Thread by =?Utf-8?B?cGF0cmlja2RyZA==?= | last post: by 10 posts views Thread by Bo Yang | last post: by 23 posts views Thread by dkirkdrei | last post: by 3 posts views Thread by newbtemple | last post: by reply views Thread by Charles Coldwell | last post: by 30 posts views Thread by copx | last post: by reply views Thread by eddparker01 | last post: by reply views Thread by eddparker01 | last post: by reply views Thread by isladogs | last post: by 1 post views Thread by isladogs | last post: by reply views Thread by Trystan | last post: by 6 posts views Thread by Kwabena10 | last post: by 1 post views Thread by Waqarahmed | last post: by 1 post views Thread by skydivetom | last post: by reply views Thread by WIPE | last post: by