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

Integer division: How do you produce a double?

提问人:walnutmon 提问时间:6/30/2010 最后编辑:Tomwalnutmon 更新时间:8/11/2020 访问量:532089

问:

对于此代码块:

int num = 5;
int denom = 7;
double d = num / denom;

的值为 。它可以通过铸造来强制工作:d0.0

double d = ((double) num) / denom;

但是有没有其他方法可以获得正确的结果呢?我不喜欢投射基元,谁知道会发生什么。double

Java 强制转换 整数除法

评论

14赞 Peter Lawrey 6/30/2010
将“int”转换为双精度值是安全的,您将始终获得相同的值而不会损失精度。
1赞 mannyee 11/21/2014
我想知道以下是否是编译器为除法采取的正确步骤:1) 将 num 转换为浮点数 2) 将 denom 转换为浮点数 2) 将 num 除以 denom。如果我不正确,请告诉我。

答:

193赞 Matthew Flaschen 6/30/2010 #1
double num = 5;

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

扩大基元转换不会 丢失有关整体的信息 数值的大小。

[...]

int 或 long 值的转换 浮点数,或长整型值 双倍,可能导致损失 精度——也就是说,结果可能会丢失 一些最不重要的位 值。在这种情况下,结果 浮点值将为 正确舍入的版本 整数值,使用 IEEE 754 舍入到最近模式 (§4.2.4)。

5 可以精确地表示为双精度。

评论

74赞 Mark Peters 6/30/2010
+1.不要再害怕选角了。了解其工作原理。这一切都是明确定义的。
1赞 Vitruvie 2/23/2014
@FabricioPH 这适用于各种情况,并且与 *1.0 解决方案相同。
3赞 Rudolf Real 3/1/2014
@Saposhiente 它超越了工作与否。更改变量的类型对我来说似乎是肮脏的代码。如果你有一个必须是整数的东西,并且你为了能够执行数学运算而更改了浮点数的表示形式,你可能会冒着风险。此外,在某些情况下,将变量作为整数读取会使代码更易于理解。
2赞 Matthew Flaschen 3/3/2014
@FabricioPH,乘以仍然会更改结果的类型,只是方式不同。“在我看来,代码很脏”并没有解释你认为在什么情况下乘以实际上更好(或者为什么会这样)。1.01.0
5赞 Paul Tomblin 3/28/2015
@FabricioPH 你和 OP 似乎在错误的信念下工作(你说“改变变量的类型”),即以某种方式改变.它不会 - 它为语句的上下文创建一个临时的替身。(double)numnum
126赞 Paul Tomblin 6/30/2010 #2

转换基元有什么问题?

如果你因为某种原因不想投,你可以做

double d = num * 1.0 / denom;

评论

76赞 Alice Purcell 6/2/2011
...在乘法之前进行隐式强制转换
2赞 Rudolf Real 8/20/2012
在大多数情况下,这比更改其他变量的类型要好。
4赞 Vitruvie 2/23/2014
@FabricioPH 除非你有来源可以引用,否则没有任何迹象表明这是真的。
1赞 Rudolf Real 3/1/2014
@Saposhiente您在其他类似评论中回复了
2赞 BrainSlugs83 10/6/2014
您还可以使用“D”后缀(执行相同的隐式强制转换);-- 例如:double d = num * 1D / denom;
89赞 Jesper 6/30/2010 #3

我不喜欢投射基元,谁知道会发生什么。

为什么你对投射基元有一种非理性的恐惧?当您将 .如果您不确定它是如何工作的,请在 Java 语言规范中查找它。将 to 转换为是不断扩大的原始转换intdoubleintdouble

您可以通过转换分母而不是分子来删除额外的一对括号:

double d = num / (double) denom;

评论

3赞 user85421 6/30/2010
你也可以做......(好的,这个取决于优先级)double d = (double) num / denom;
34赞 alianos- 5/23/2013 #4

如果你改变一个变量的类型,你必须记住,如果你的公式改变,你要再次偷偷溜进双精度,因为如果这个变量不再是计算的一部分,结果就会搞砸。我养成了在计算中强制转换的习惯,并在其旁边添加注释。

double d = 5 / (double) 20; //cast to double, to do floating point calculations

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

double d = (double)(5 / 20); //produces 0.0
22赞 Nikhil Kumar 4/14/2015 #5

将其中一个整数/两个整数转换为浮点数,以强制使用浮点数学完成运算。 否则,始终首选整数数学。所以:

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

我不认为你正在考虑的选角有任何问题。

2赞 ungalcrys 9/14/2015 #6

使用类似的东西:

double step = 1d / 5;

(1d 是 double 的投射)

评论

10赞 Sefier Tang 11/14/2015
1D 不是演员表,它只是一个声明。
27赞 Minhas Kamal 4/7/2016 #7

类型铸造是唯一的办法

也许你不会明确地这样做,但它会发生。

现在,有几种方法可以尝试获得精确的值(where 和 are 类型,当然还有铸造doublenumdenomint)-

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


现在,如果你问--哪个更好?明确?还是隐含的?

好吧,我们不要在这里遵循一个直接的答案。请记住 - 我们程序员不喜欢源代码中的惊喜或魔法。我们真的很讨厌复活节彩蛋。

此外,额外的操作绝对不会使您的代码更有效率。右?

评论

1赞 Quimbo 2/25/2021
如果它是浮点数,这也有效吗?
0赞 Ken Wayne VanderLinde 9/3/2016 #8

您可以考虑包装操作。例如:

class Utils
{
    public static double divide(int num, int denom) {
        return ((double) num) / denom;
    }
}

这使您可以查找(仅一次)演员是否完全符合您的要求。此方法也可以进行测试,以确保它继续执行您想要的操作。你用什么技巧来引起分裂也没关系(你可以在这里使用任何答案),只要它产生正确的结果。在需要除以两个整数的任何地方,您现在只需调用并相信它做了正确的事情。Utils::divide

0赞 Mabood Ahmad 4/25/2017 #9

就用这个。

int fxd=1;
double percent= (double)(fxd*40)/100;
2赞 Alp Altunel 8/16/2017 #10

最好的方法是

int i = 3;
Double d = i * 1.0;

d is 3.0 now.
0赞 Ricardo 8/11/2020 #11

只需添加“D”即可。

int i = 6;
double d = i / 2D; // This will divide bei double.
System.out.println(d); // This will print a double. = 3D

评论

0赞 AndrewF 8/15/2020
对于人类来说,小数后缀通常更清晰。 是下一个最佳选择。我认为这是有害的,因为它看起来太像数字而无法与数字相邻。.0dD