What is the rationale for not throwing
exceptions in these cases? Is this an
IEEE standard, or was it merely a
choice by the designers of Java?
The IEEE 754-1985 Standard in pages 20 and 21 under the sections 2.2.1 NANs and 2.2.2 Infinity clearly explains the reasons why NAN and Infinity values are required by the standard. Therefore this not a Java thing.
The Java Virtual Machine Specification in section 3.8.1 Floating Point Arithmetic and IEEE 754 states that when conversions to integral types are carried out then the JVM will apply rounding toward zero which explains the results you are seeing.
The standard does mention a feature named "trap handler" that could be used to determine when overflow or NAN occurs but the Java Virtual Machine Specification clearly states this is not implemented for Java. It says in section 3.8.1:
The floating-point operations of the
Java virtual machine do not throw
exceptions, trap, or otherwise signal
the IEEE 754 exceptional conditions of
invalid operation, division by zero,
overflow, underflow, or inexact. The
Java virtual machine has no signaling
NaN value.
So, the behavior is not unspecified regardless of consequences.
Are there bad consequences that I am
unaware of if exceptions would be
possible with such casts?
Understanding the reasons stated in standard should suffice to answer this question. The standard explains with exhaustive examples the consequences you are asking for here. I would post them, but that would be too much information here and the examples can be impossible to format appropriately in this edition tool.
EDIT
I was reading the latest maintenance review of the Java Virtual Machine Specification as published recently by the JCP as part of their work on JSR 924 and in the section 2.11.14 named type conversion istructions contains some more information that could help you in your quest for answers, not yet what you are looking for, but I believe it helps a bit. It says:
In a narrowing numeric conversion of a
floating-point value to an integral
type T, where T is either int or long,
the floating-point value is converted
as follows:
- If the floating-point value is NaN, the result of the conversion is an
int or long 0.
- Otherwise, if the floating-point value is not an infinity, the
floating-point value is rounded to
an integer value V using IEEE 754
round towards zero mode.
There are two cases:
- If T is long and this integer value can be represented as a long, then
the result is the long value V.
- If T is of type int and this integer value can be represented as
an int, then the result is the int
value V.
Otherwise:
- Either the value must be too small (a negative value of large
magnitude or negative infinity),
and the result is the smallest
representable value of type int or
long.
- Or the value must be too large (a positive value of large magnitude or
posi- tive infinity), and the result
is the largest representable value of
type int or long.
A narrowing numeric conversion from
double to float behaves in accordance
with IEEE 754. The result is correctly
rounded using IEEE 754 round to
nearest mode. A value too small to be
represented as a float is converted to
a positive or negative zero of type
float; a value too large to be
represented as a float is converted to
a positive or negative infinity. A
double NaN is always converted to
a float NaN.
Despite the fact that overflow,
underflow, or loss of precision
may occur, narrowing conversions among
numeric types never cause the
Java virtual machine to throw a
runtime exception (not to be confused
with an IEEE 754 floating-point
exception).
I know this simply restates what you already know, but it has a clue, it appears that the IEEE standard has a requirement of rounding to the nearest. Perhaps there you can find the reasons for this behavior.
EDIT
The IEEE Standard in question in section 2.3.2 Rounding Modes States:
By
default, rounding means round toward
the
nearest. The standard requires that three other
rounding modes be provided; namely, round toward
0, round toward +Infinity and round toward –Infinity.
When used with the convert to integer operation, round toward –Infinity causes the convert to become the floor function, whereas, round toward +Infinity
is ceiling.
The mode rounding affects overflow because when round toward O or round toward
-Infinite is in effect, an overflow of positive magnitude causes the default result to be the largest representable number, not +Infinity.
Similarly, overflows of
negative magnitude will produce
the largest negative number when round toward +Infinity or round toward O is in effect.
Then they proceed to mention an example of why this is useful in interval arithmetic. Not sure, again, that this is the answer you are looking for, but it can enrich your search.