可能导致精度或幅度损失的 Java 隐式强制转换? [复制]

Posted

技术标签:

【中文标题】可能导致精度或幅度损失的 Java 隐式强制转换? [复制]【英文标题】:Java implicit casts that can lead to precision or magnitude loss? [duplicate] 【发布时间】:2012-12-06 16:23:24 【问题描述】:

我最近learned,在将一些 Java 代码转换为 C# 时,Java 的增量运算符 '+=' 隐式转换为 LHS 的类型:

int i = 5;
long lng = 0xffffffffffffL;  //larger than Int.MAX_VALUE
i += lng;                    //allowed by Java (i==4), rejected by C#

相当于:(details here)

int i = 0;
long lng = 0xffffffffffffL;
i = (int)(i + lng);

从而默默地造成损失幅度的机会。

C# 在编译时对此更加认真:Cannot convert source type long to target type int.

Java 是否允许其他类似的情况?

【问题讨论】:

可能是因为这不是关于 C# 的问题,它只是指它??当人们仅仅因为他们在问题中提到它而包含 [java] 时,我发现它很烦人(但我不反对)。 @Peter 好的,你可能有道理。当我问这个问题时,我的心态非常 C#-y(在修复从 Java 转换而来的 C# 代码方面非常努力)。从未想过从读者的角度添加标签 :) [C# 标签已删除] 我只是在这里猜测。当人们投反对票时,我觉得很烦,但没有评论为什么。这就像告诉你;我觉得你做错了什么,但我没有告诉你是什么,或者我什至不知道这是什么。 ;) @Peter 所以...嗯,为什么要删除你的答案? 虽然在我给出的示例中它很相似,但它与隐式强制转换不同。 Meriton 指出你不能给它超出范围的值,我注意到你不能写 byte b = 1.0; 但你可以写 b += 1.0; 【参考方案1】:

long 可以提升为 float 或 double,这会导致精度损失:

public static void main(String[] args) 
    float f = Long.MAX_VALUE;
    double d = Long.MAX_VALUE;

    System.out.println(Long.MAX_VALUE);
    System.out.println(f);
    System.out.println(d);


打印

9223372036854775807
9.223372E18
9.223372036854776E18

不过,我怀疑 C# 也是这样做的。

除了你已经提到的复合赋值运算符之外,我相信这些都是隐式转换可以改变值的所有情况。

【讨论】:

floatdouble 的转换可能会使排名发生数百或几个数量级的变化。给定float f=1E20; float f2=f*f; double d = 1E300;f2(float)d 之间的比较将正确地认为这些值无法区分。另一方面,比较d(double)f2 将表明df2,即使它应该大240 个数量级。 您的示例无法支持您的主张,因为它使用了 explicit 转换,该转换可以(并且在这种情况下确实)更改了值。具体来说,我们有((float) d) != d((double) f2) == f2

以上是关于可能导致精度或幅度损失的 Java 隐式强制转换? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

改变行为可能导致精度损失

Java类型转换

JAVA数据类型及其强制转换

2020-12-05

java读取文件时 int强制转换为 byte,是如何保证结果正确的??不是损失了精度吗??

传递变量作为函数参数时由于隐式铸造导致的精度损失