整数除法:你如何产生双倍?

wal*_*mon 232 java casting integer-division

对于此代码块:

int num = 5;
int denom = 7;
double d = num / denom;
Run Code Online (Sandbox Code Playgroud)

价值d0.0.它可以通过强制转换来强制工作:

double d = ((double) num) / denom;
Run Code Online (Sandbox Code Playgroud)

但还有另一种方法可以获得正确的double结果吗?我不喜欢铸造原始人,谁知道会发生什么.

Mat*_*hen 148

double num = 5;
Run Code Online (Sandbox Code Playgroud)

这避免了演员.但是你会发现演员转换是明确定义的.您不必猜测,只需检查JLS即可.int to double是一个扩大的转换.从§5.1.2开始:

扩展原始转换不会丢失有关数值总体大小的信息.

[...]

将int或long值转换为float,或将long值转换为double,可能会导致精度损失 - 也就是说,结果可能会丢失该值的一些最低有效位.在这种情况下,使用IEEE 754舍入到最接近模式(第4.2.4节)生成的浮点值将是整数值的正确舍入版本.

5可以精确表示为double.

  • +1.不要害怕铸造.了解它是如何工作的.这一切都很明确. (57认同)
  • @FabricioPH你和OP似乎在错误的信念(你说"改变变量的类型")下工作,即`(double)num`以某种方式改变`num`.它没有 - 它为语句的上下文创建一个临时的双重. (4认同)
  • @Saposhiente它超越了工作与否.改变变量的类型对我来说似乎是脏代码.如果你有一些东西必须是一个整数,你改变浮动的表示只是为了能够执行数学运算,你可能会冒自己的风险.此外,在某些上下文中,将变量读取为整数会使代码更易于理解. (3认同)
  • @FabricioPH,乘以"1.0"仍会改变结果的类型,只是以不同的方式."对我来说似乎是脏代码"并没有解释你认为在什么情况下乘以"1.0"实际上更好(或者为什么会这样). (2认同)

Pau*_*lin 94

铸造原语有什么问题?

如果你因某些原因不想演员,你可以这样做

double d = num * 1.0 / denom;
Run Code Online (Sandbox Code Playgroud)

  • ...在乘法之前进行隐式转换 (61认同)
  • @FabricioPH没有任何迹象表明这是真的,除非你有一个引用的来源. (3认同)
  • 在大多数情况下,这比改变其他变量的类型要好. (2认同)
  • 您还可以使用“D”后缀(执行相同的隐式转换);-- 例如:`double d = num * 1D / denom;` (2认同)

Jes*_*per 67

我不喜欢铸造原始人,谁知道会发生什么.

为什么你对投射原语有一种非理性的恐惧?当你施放一个没什么不好会发生intdouble.如果您不确定它是如何工作的,请在Java语言规范中查找.铸造intdouble是一个加宽原语转换.

您可以通过投射分母而不是分子来摆脱额外的括号:

double d = num / (double) denom;
Run Code Online (Sandbox Code Playgroud)

  • 您也可以执行`double d =(double)num / denom;`...(确定,这取决于优先级) (2认同)

ali*_*os- 25

如果您更改了一个必须记住的变量的类型,如果您的公式发生更改,则再次潜入一个double,因为如果此变量不再是计算的一部分,则结果会搞砸.我养成了在计算中投射的习惯,并在旁边添加注释.

double d = 5 / (double) 20; //cast to double, to do floating point calculations
Run Code Online (Sandbox Code Playgroud)

请注意,转换结果不会这样做

double d = (double)(5 / 20); //produces 0.0
Run Code Online (Sandbox Code Playgroud)


Nik*_*mar 15

将其中一个整数/两个整数转换为float以强制使用浮点Math完成操作.否则,整数Math始终是首选.所以:

1. double d = (double)5 / 20;
2. double v = (double)5 / (double) 20;
3. double v = 5 / (double) 20;
Run Code Online (Sandbox Code Playgroud)

请注意,转换结果不会这样做.因为第一次划分是按照优先规则完成的.

double d = (double)(5 / 20); //produces 0.0
Run Code Online (Sandbox Code Playgroud)

我不认为你正在思考的是铸造有什么问题.


Min*_*mal 8

类型铸造是唯一的方法


double从整数除法产生一个 - 没有其他方式没有强制转换(可能你不会明确地做,但它会发生).

现在,有几种方法可以尝试获得精确的double值(其中num,并denomint型,和当然有铸造) -

  1. 使用显式转换:

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

  1. 隐式转换:

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