对于此代码块:
int num = 5; int denom = 7; double d = num / denom;
价值d
是0.0
.它可以通过强制转换来强制工作:
double d = ((double) num) / denom;
但还有另一种方法可以获得正确的double
结果吗?我不喜欢铸造原始人,谁知道会发生什么.
double num = 5;
这避免了演员.但是你会发现演员转换是明确定义的.您不必猜测,只需检查JLS即可.int to double是一个扩大的转换.从§5.1.2开始:
扩展原始转换不会丢失有关数值总体大小的信息.
[...]
将int或long值转换为float,或将long值转换为double,可能会导致精度损失 - 也就是说,结果可能会丢失该值的一些最低有效位.在这种情况下,使用IEEE 754舍入到最接近模式(第4.2.4节)生成的浮点值将是整数值的正确舍入版本.
5可以精确表示为double.
铸造原语有什么问题?
如果你因某些原因不想演员,你可以这样做
double d = num * 1.0 / denom;
我不喜欢铸造原始人,谁知道会发生什么.
为什么你对投射原语有一种非理性的恐惧?当你施放一个没什么不好会发生int
的double
.如果您不确定它是如何工作的,请在Java语言规范中查找.铸造int
到double
是一个加宽原语转换.
您可以通过投射分母而不是分子来摆脱额外的括号:
double d = num / (double) denom;
如果您更改了一个必须记住的变量的类型,如果您的公式发生更改,则再次潜入一个double,因为如果此变量不再是计算的一部分,则结果会搞砸.我养成了在计算中投射的习惯,并在旁边添加注释.
double d = 5 / (double) 20; //cast to double, to do floating point calculations
请注意,转换结果不会这样做
double d = (double)(5 / 20); //produces 0.0
将其中一个整数/两个整数转换为float以强制使用浮点Math完成操作.否则,整数Math始终是首选.所以:
1. double d = (double)5 / 20; 2. double v = (double)5 / (double) 20; 3. double v = 5 / (double) 20;
请注意,转换结果不会这样做.因为第一次划分是按照优先规则完成的.
double d = (double)(5 / 20); //produces 0.0
我不认为你正在思考的是铸造有什么问题.
double
从整数除法产生一个 - 没有其他方式没有强制转换(可能你不会明确地做,但它会发生).
现在,有几种方法可以尝试获得精确的double
值(其中num
,并denom
有int
型,和当然有铸造) -
使用显式转换:
double d = (double) num / denom;
double d = ((double) num) / denom;
double d = num / (double) denom;
double d = (double) num / (double) denom;
但不是 double d = (double) (num / denom);
隐式转换:
double d = num * 1.0 / denom;
double d = num / 1d / denom;
double d = ( num + 0.0 ) / denom;
double d = num; d /= denom;
但不是double d = num / denom * 1.0;
也不是double d = 0.0 + ( num / denom );