ChatGPT解决这个技术问题 Extra ChatGPT

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

对于此代码块:

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

d 的值为 0.0。它可以通过强制转换强制工作:

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

但是还有其他方法可以获得正确的 double 结果吗?我不喜欢铸造原语,谁知道会发生什么。

将“int”转换为双精度是安全的,您将始终获得相同的值而不会损失精度。
我想知道以下是否是编译器为除法所采取的正确步骤:1)将 num 转换为 float 2)将 denom 转换为 float 2)将 num 除以 denom。如果我不正确,请告诉我。

M
Mindwin
double num = 5;

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

扩大原始转换不会丢失有关数值整体大小的信息。 [...] 将 int 或 long 值转换为 float,或将 long 值转换为 double,可能会导致精度损失——也就是说,结果可能会丢失值的一些最低有效位。在这种情况下,生成的浮点值将是整数值的正确舍入版本,使用 IEEE 754 舍入到最近模式(第 4.2.4 节)。

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


+1。别再害怕选角了。了解它是如何工作的。这一切都很好定义。
@FabricioPH 这适用于任何情况,与 *1.0 解决方案相同。
@Saposhiente 它超越了工作与否。更改变量的类型对我来说似乎是肮脏的代码。如果您有一些必须是整数的东西,并且您更改浮点数的表示只是为了能够执行数学运算,那么您可能会冒险。同样在某些情况下,将变量读取为整数会使代码更容易理解。
@FabricioPH,乘以 1.0 仍然会改变结果的类型,只是方式不同。 “对我来说似乎是脏代码”并没有解释在什么情况下您认为乘以 1.0 实际上更好(或者为什么会这样)。
@FabricioPH您和OP似乎在错误的信念(您说“更改变量的类型”)下工作(double)num会以某种方式改变num。它没有 - 它为语句的上下文创建一个临时的双精度值。
P
Paul Tomblin

铸造原语有什么问题?

如果您出于某种原因不想投射,您可以这样做

double d = num * 1.0 / denom;

...在乘法之前进行隐式转换
在大多数情况下,这比更改其他变量的类型要好。
@FabricioPH 除非您有可引用的来源,否则没有任何迹象表明这是真的。
@Saposhiente 在您的其他类似评论中回复
您还可以使用“D”后缀(执行相同的隐式转换); -- 例如:double d = num * 1D / denom;
B
Bernhard Barker

我不喜欢铸造原语,谁知道会发生什么。

为什么你对铸造原语有一种非理性的恐惧?将 int 转换为 double 不会发生任何坏事。如果您不确定它是如何工作的,请在 Java Language Specification 中查找。将 int 投射到 doublewidening primitive conversion

您可以通过转换分母而不是分子来摆脱多余的括号:

double d = num / (double) denom;

你也可以做 double d = (double) num / denom;...(好的,这取决于优先级)
a
alianos-

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

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

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

double d = (double)(5 / 20); //produces 0.0

M
Minhas Kamal

类型转换是唯一的方法

可能你不会明确地这样做,但它会发生。

现在,有几种方法可以尝试获得精确的 double 值(其中 numdenomint 类型,当然使用强制转换)-

显式转换:

双 d = (双) 数量 / denom;

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

double d = num / (double) denom;

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

但不是double d = (double) (num / denom);

隐式转换:

双 d = num * 1.0 / denom;

双 d = num / 1d / denom;

双 d = ( num + 0.0 ) / denom;

双 d = 数字; d /= 面额;

但不是 double d = num / denom * 1.0;
而不是 double d = 0.0 + ( num / denom );

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

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

此外,额外的操作肯定不会让您的代码更有效率。正确的?


如果它是浮点数,这也有效吗?
N
Nikhil Kumar

将整数之一/两个整数强制转换为浮点数以强制使用浮点数学来完成操作。否则整数数学总是首选。所以:

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

我认为您正在考虑的铸造没有任何问题。


u
ungalcrys

使用类似的东西:

double step = 1d / 5;

(1d 是加倍的演员表)


1d 不是演员表,它只是一个声明。
A
Alp Altunel

最好的方法是

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

d is 3.0 now.

K
Ken Wayne VanderLinde

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

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

这使您可以查看(仅一次)演员是否完全按照您的意愿行事。这种方法也可以接受测试,以确保它继续做你想做的事。您使用什么技巧来引起除法也无关紧要(您可以在此处使用任何答案),只要它产生正确的结果即可。在任何需要将两个整数相除的地方,您现在只需调用 Utils::divide 并相信它会做正确的事。


F
FelixSFD

就用这个。

int fxd=1;
double percent= (double)(fxd*40)/100;

R
Ricardo

只需添加“D”。

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

分数后缀 .0 通常对人类来说更清楚。 d 是次佳选项。我认为 D 是有害的,因为它看起来太像数字而不能与数字相邻。