Velocity Reviews > Java > Division by zero: float vs. int

# Division by zero: float vs. int

Razvan
Guest
Posts: n/a

 09-28-2004
Tor Iver Wilhelmsen <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>...
> http://www.velocityreviews.com/forums/(E-Mail Removed) (Razvan) writes:
>
> > What is the reason for this behavior ? Why integers throw exceptions
> > when dividing by zero while floats just assumes the number is Infinity
> > (no exception is thrown) ?

>
> Because the IEEE standard for floating point numbers used has defined
> values for positive and negative infinity, and the special "not a
> number" case. See the contants in java.lang.Float and java.lang.Double
> for details.

So, this is the reason: the IEEE specification is different
for integers and floats. Maybe the float specification is newer and
for this reason it contains new 'items' like +Infinity, -Infinity and
NaN.

> (NaN has some special properties the following class demonstrates:

Yes, that is true. 2 NaNs are never equal.

Regards,
Razvan

Tor Iver Wilhelmsen
Guest
Posts: n/a

 09-28-2004
(E-Mail Removed) (Razvan) writes:

> I know that. My question was "why ?". Why we are treating
> integers and floats differenntly ? Why integers don't have NaN
> representions ? Certainly with integer operation you can get NaNs.

Because the floating point representation has bit patterns that are
set aside for the purpose. You cannot do the same for integers since

1) It would reduce the available value range.

2) You cannot reliably (except in Java, C# and the like) "know" how
large an integer is. If you declare 0xffffffff to be positive (or
negative?) infinity, you will run into trouble on machines with
larger representations of ints. Also, integers are often either
signed or unsigned - floating point is always signed.

Dimitri Maziuk
Guest
Posts: n/a

 09-28-2004
Razvan sez:
> "Michael Saunby" <(E-Mail Removed)> wrote in message news:<cj8v46\$og6\$1\$(E-Mail Removed)>...
>> "Razvan" <(E-Mail Removed)> wrote in message
>> news:(E-Mail Removed) om...
>>
>> [snip]
>>
>> >
>> > What is the reason for this behavior ? Why integers throw exceptions
>> > when dividing by zero while floats just assumes the number is Infinity
>> > (no exception is thrown) ?
>> >

>>
>> Floating point representations usually include +inf, -inf and even "Not a
>> Number". Integer representations don't.

>
> I know that. My question was "why ?". Why we are treating
> integers and floats differenntly ? Why integers don't have NaN
> representions ? Certainly with integer operation you can get NaNs.

Beacuse in two's complement binary all possible bit patterns
represent valid integers. I.e. there is no bit pattern for
integer NaN, instead there's an extra integer at the negative
end of (signed) range.

The only explanation why we're not using one's complement
I've heard is "because one's complement has a bit pattern
for negative zero which mathematically doesn't make sense".
Nobody seems to care that programmatically it makes perfect
sense to use that bit pattern to represent integer NaN.
Go figure.

Dima
--
All whitespace is equivalent except in certain cituations
-- ANSI C standard committee

Thomas G. Marshall
Guest
Posts: n/a

 09-28-2004
Dimitri Maziuk coughed up:
> Razvan sez:
>> "Michael Saunby" <(E-Mail Removed)> wrote in message
>> news:<cj8v46\$og6\$1\$(E-Mail Removed)>...
>>> "Razvan" <(E-Mail Removed)> wrote in message
>>> news:(E-Mail Removed) om...
>>>
>>> [snip]
>>>
>>>>
>>>> What is the reason for this behavior ? Why integers throw
>>>> exceptions when dividing by zero while floats just assumes the
>>>> number is Infinity (no exception is thrown) ?
>>>>
>>>
>>> Floating point representations usually include +inf, -inf and even
>>> "Not a Number". Integer representations don't.

>>
>> I know that. My question was "why ?". Why we are treating
>> integers and floats differenntly ? Why integers don't have NaN
>> representions ? Certainly with integer operation you can get NaNs.

>
> Beacuse in two's complement binary all possible bit patterns
> represent valid integers. I.e. there is no bit pattern for
> integer NaN, instead there's an extra integer at the negative
> end of (signed) range.
>
> The only explanation why we're not using one's complement
> I've heard is "because one's complement has a bit pattern
> for negative zero which mathematically doesn't make sense".

No.

Two's compliment allows for a negative representation to be added without
regard to sign to a positive representation and yield an effective
subtraction. The "add" need not even care, or if it does, it is relegated

Think on an 8 bit processor register A having the value 10. And now you
wish to add to it an value in the register B

If the value of B is +1, then adding is easy:

10 + 1 = 11

If the value of B is -1 it is really 255 (in two's complement) and adding

10 + 255 = 9

Because the value would "pass over" 256 and start over. It all just works:
the "add" operation need not care /what/ sign you think B is.

IF we were in one's compliment, a negative 1 would be 254. which means that
the "add" needs to be sign cognizant.

....[rip]...

--
"It's easier to be terrified by an enemy you admire."
-Thufir Hawat, Mentat and Master of Assassins to House Atreides

Thomas G. Marshall
Guest
Posts: n/a

 09-28-2004
Thomas G. Marshall coughed up:
> Dimitri Maziuk coughed up:
>> Razvan sez:
>>> "Michael Saunby" <(E-Mail Removed)> wrote in message
>>> news:<cj8v46\$og6\$1\$(E-Mail Removed)>...
>>>> "Razvan" <(E-Mail Removed)> wrote in message
>>>> news:(E-Mail Removed) om...
>>>>
>>>> [snip]
>>>>
>>>>>
>>>>> What is the reason for this behavior ? Why integers throw
>>>>> exceptions when dividing by zero while floats just assumes the
>>>>> number is Infinity (no exception is thrown) ?
>>>>>
>>>>
>>>> Floating point representations usually include +inf, -inf and even
>>>> "Not a Number". Integer representations don't.
>>>
>>> I know that. My question was "why ?". Why we are treating
>>> integers and floats differenntly ? Why integers don't have NaN
>>> representions ? Certainly with integer operation you can get NaNs.

>>
>> Beacuse in two's complement binary all possible bit patterns
>> represent valid integers. I.e. there is no bit pattern for
>> integer NaN, instead there's an extra integer at the negative
>> end of (signed) range.
>>
>> The only explanation why we're not using one's complement
>> I've heard is "because one's complement has a bit pattern
>> for negative zero which mathematically doesn't make sense".

>
> No.
>
> Two's compliment allows for a negative representation to be added
> without regard to sign to a positive representation and yield an
> effective subtraction. The "add" need not even care, or if it does,
> it is relegated to worrying about overflow

and carry

> bits.
>
> Think on an 8 bit processor register A having the value 10. And now
> you wish to add to it an value in the register B
>
>
> If the value of B is +1, then adding is easy:
>
> 10 + 1 = 11
>
> If the value of B is -1 it is really 255 (in two's complement) and
>
> 10 + 255 = 9
>
> Because the value would "pass over" 256 and start over. It all just
> works: the "add" operation need not care /what/ sign you think B is.
>
> IF we were in one's compliment, a negative 1 would be 254. which
> means that the "add" needs to be sign cognizant.
>
>
> ...[rip]...

--
"It's easier to be terrified by an enemy you admire."
-Thufir Hawat, Mentat and Master of Assassins to House Atreides

Thomas G. Marshall
Guest
Posts: n/a

 09-28-2004
Tor Iver Wilhelmsen coughed up:
> (E-Mail Removed) (Razvan) writes:
>
>> What is the reason for this behavior ? Why integers throw exceptions
>> when dividing by zero while floats just assumes the number is
>> Infinity (no exception is thrown) ?

>
> Because the IEEE standard for floating point numbers used has defined
> values for positive and negative infinity, and the special "not a
> number" case. See the contants in java.lang.Float and java.lang.Double
> for details.
>
> (NaN has some special properties the following class demonstrates:
>
> public class DoubleTest {
> public static void main(String[] _) {
> // Prints "false"
> System.out.println("Double.NaN == Double.NaN: "
> + (Double.NaN == Double.NaN));
> // Prints NaN
> System.out.println("sqrt(-1.0) = "+Math.sqrt(-1.0));
> }
> }
>
> )

I've often pondered on this for years. What is the advantage to disallowing

Double.Nan == Double.Nan

aside from the (IMO unimportant) fact that it might be possible for multiple
bit representations to be NaN?

--
"It's easier to be terrified by an enemy you admire."
-Thufir Hawat, Mentat and Master of Assassins to House Atreides

Eric Sosman
Guest
Posts: n/a

 09-28-2004
Thomas G. Marshall wrote:
> [...]
> Two's compliment allows [...]
> IF we were in one's compliment [...]

For future reference, it's "complement," with two
e's and no i's. "Two's compliment" is something nice
said by a two.

The truly picky pedant may also wish to consider
Knuth's assertion (TAOCP vII, sec 4.1) that the way to
place the apostrophes is "two's complement" but "ones'
complement." I don't know whether his argument is
widely accepted, but it makes sense.

--
(E-Mail Removed)

Eric Sosman
Guest
Posts: n/a

 09-28-2004
Thomas G. Marshall wrote:
>
> I've often pondered on this for years. What is the advantage to disallowing
>
> Double.Nan == Double.Nan
>
> aside from the (IMO unimportant) fact that it might be possible for multiple
> bit representations to be NaN?

I wasn't at Kahan's elbow when this was being dreamed
up, but I'll risk a speculation anyhow.

Here are a few computations that yield NaNs. Which
pairs should be considered equal?

double x1 = Math.sqrt(-1);
double x2 = Math.sqrt(-2);
double x3 = Double.POSITIVE_INFINITY
- Double.POSITIVE_INFINITY;
double x4 = Double.NEGATIVE_INFINITY
+ Double.POSITIVE_INFINITY;
double x5 = Math.PI / Double.NaN;

It seems (to me, anyhow) that considering any pair of these
to be "equal" would be a Bad Thing. So it seems reasonable
to consider NaNs "unequal" if they arise from different
calculations. And since there's a potentially infinite
set of calculations but a finite set of representable NaNs,
it's not even safe to consider two NaNs with identical bit
patterns to be equal; they might have arisen from different
causes that happened to map to the same batch of bits.

Here's another example that (I think) would suffer if
even "the same" NaN were considered equal to itself. Let's
write ourselves a string-to-double converter that handles
invalid input by returning a NaN instead of throwing an
exception:

static double stringToDouble(String string) {
try {
return Double.valueOf(string);
}
catch (NumberFormatException ex) {
return Double.NaN;
}
}

Now: should stringToDouble("Eiffel Tower") be considered
equal to stringToDouble("colorless green ideas")? I cannot
think of any benefit to thinking of these as "equal," even
though they return "the same" NaN. So it seems that a NaN
should not even be "equal" to itself.

Oddly enough, the equals() method of Double doesn't
follow this convention, and can disagree with the ordinary
`==' operator:

Double d = new Double(Double.NaN);
System.out.println(d.doubleValue()
== d.doubleValue());
System.out.println(d.equals(d));

prints "false" first (in accordance with IEEE convention)
but then prints "true"! The rationale (or rationalization)
is in the Javadoc for the method.

--
(E-Mail Removed)

Stefan Schulz
Guest
Posts: n/a

 09-28-2004
On Tue, 28 Sep 2004 16:56:38 GMT, Thomas G. Marshall
<(E-Mail Removed). com> wrote:

> I've often pondered on this for years. What is the advantage to
> disallowing
>
> Double.Nan == Double.Nan
>
> aside from the (IMO unimportant) fact that it might be possible for
> multiple bit representations to be NaN?

The fact that it makes no sense logicwise. Is the natural Logarithm of -2
the
same as the natural Logarithm of -5?

--

Whom the gods wish to destroy they first call promising.

Dimitri Maziuk
Guest
Posts: n/a

 09-28-2004
Thomas G. Marshall sez:
[ two's complement ]
.... just works: the "add" operation need not care /what/ sign you think B is.
>>
>> IF we were in one's compliment, a negative 1 would be 254. which
>> means that the "add" needs to be sign cognizant.

I.e. if the value overflows you need to add one. The adder would
obviously have to be more complex: it'd have to know to add the
overflow bit to final result. (OK, I am oversimplifying a lot
for dramatic effect, but still...)

Problem is, complexity didn't go away just because we came up
with two's complement. All we accomplished is, we now have to
deal with it at a higher level.

E.g. you have to call ResultSet.wasNull() after ResultSet.getXXX(),
and ResultSet has to have an extra boolean flag to support that.
E.g. array search has to return -n for "not found", which means you
can't have an array [-n..m]. A function that returns a signed integer
cannot return an error value, ever. Etfc.

The \$15 question is whether the savings we get from having a simpler
adder outweigh the costs of extra complexity in the software.

Dima
--
Sufficiently advanced incompetence is indistinguishable from malice.