Division by zero: float vs. int

R

Razvan

Hi !




I have noticed that the division by zero is handled differently for
integer and float types.
Let me explain better:


public class CDummy // this class prints "Infinity" (division by zero)
{
public static void main(String args[])
{
System.out.println("CDummy.");

float f1 = 1.41356f;
float f2 = 0f;

System.out.println("f1/f2 = " + (f1/f2));
}
}




public class CDummy // this class throws an exception (division by
zero)
{
public static void main(String args[])
{
System.out.println("CDummy.");

int i1 = 1;
int i2 = 0;

System.out.println("i1/i2 = " + (i1/i2));
}
}

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) ?





Regards,
Razvan
 
M

Michael Saunby

[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. The behaviour you're seeing isn't
unique to Java, most programming languages will do something similar,
because that's what the floating point hardware (or low level library) is
doing.

Michael Saunby
 
T

Tor Iver Wilhelmsen

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));
}
}

)
 
J

John C. Bollinger

Michael said:
[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. The behaviour you're seeing isn't
unique to Java, most programming languages will do something similar,
because that's what the floating point hardware (or low level library) is
doing.

And, lest there be any confusion, the Java specs mandate the observed
behavior, regardless of what the underlying hardware may or may not do.

John Bollinger
(e-mail address removed)
 
T

Tor Iver Wilhelmsen

John C. Bollinger said:
And, lest there be any confusion, the Java specs mandate the observed
behavior, regardless of what the underlying hardware may or may not do.

Isn't that what the "strictfp" keyword is for though? To protect
yourself from any anomalies in the underlying hardware?
 
M

Mark Thornton

Tor said:
Isn't that what the "strictfp" keyword is for though? To protect
yourself from any anomalies in the underlying hardware?

No, even without strictfp, there remain quite tight rules on how Java is
permitted to behave.

Mark Thornton
 
?

=?ISO-8859-1?Q?Daniel_Sj=F6blom?=

Mark said:
No, even without strictfp, there remain quite tight rules on how Java is
permitted to behave.

True. Strictfp only disallows using extended precision values for
intermediate calculations. Non-strictfp code allows intermediate
calculations in extended precision, but any assignments result in a
conversion back to the standard precision value sets. Even without
strictfp, the rules are quite strict, and are in conflict with the
choices made in e.g. the x87 fpu (I seem to recall that the java
floating point semantics are taken from some of Sun's fp implementations
in software. Not surprising, really.).
 
B

Boudewijn Dijkstra

Razvan said:
Hi !




I have noticed that the division by zero is handled differently for
integer and float types.
Let me explain better:


System.out.println("1f/0f = " + (1f/0f));
System.out.println("1 /0 = " + (1 /0 ));

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) ?

From a mathematical point of view, this is because integers are always exact
and floating point numbers are not. The idea is that you 'never' know what
was truncated to fit it in a finite number of bits.
 
R

Razvan

Michael Saunby said:
[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.



Regards,
Razvan
 
S

Stefan Schulz

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.

Simple reasoning. It is very simple to implement addition for integers. It
is
much harder for floating point values. Such "Special Cases" would destroy
many, if not all sophisticated algorithms for integer addition. Since
Floating Point arithmetic is a few leagues more complicated anyway, it is
not
such a big issue here to have special cases.
 
R

Razvan

Tor Iver Wilhelmsen said:
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
 
T

Tor Iver Wilhelmsen

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.
 
D

Dimitri Maziuk

Razvan sez:
Michael Saunby said:
[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
 
T

Thomas G. Marshall

Dimitri Maziuk coughed up:
Razvan sez:
Michael Saunby said:
[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 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

Load A with 10
Add B to A

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]...
 
T

Thomas G. Marshall

Thomas G. Marshall coughed up:
Dimitri Maziuk coughed up:
Razvan sez:
[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

Load A with 10
Add B to A

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]...
 
T

Thomas G. Marshall

Tor Iver Wilhelmsen coughed up:
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?
 
E

Eric Sosman

Thomas said:
[...]
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

Eric Sosman

Thomas said:
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.
 
S

Stefan Schulz

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?
 
D

Dimitri Maziuk

Thomas G. Marshall sez:
[ two's complement ]
.... just works: the "add" operation need not care /what/ sign you think B is.
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top