不同的行为可能会导致精度下降 [英] Varying behavior for possible loss of precision

查看:187
本文介绍了不同的行为可能会导致精度下降的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java中,当你这样做时

In Java, when you do

int b = 0;
b = b + 1.0;

您可能会丢失精度错误。但是为什么如果你这样做

You get a possible loss of precision error. But why is it that if you do

int b = 0;
b += 1.0;

没有任何错误?

推荐答案

那是因为 b + = 1.0; 相当于 b =(int)((b)+ (1.0)); 缩小基元转换(JLS) 5.1.3)隐藏在复合赋值操作中。

That's because b += 1.0; is equivalent to b = (int) ((b) + (1.0));. The narrowing primitive conversion (JLS 5.1.3) is hidden in the compound assignment operation.


E1 op = E2 形式的复合赋值表达式等效于 E1 =(T)((E1)op(E2 )),其中 T E1 的类型,但 E1 仅评估一次。

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

例如,以下代码是正确的:

For example, the following code is correct:

short x = 3;
x += 4.6;

并导致 x 的值为 7 因为它相当于:

and results in x having the value 7 because it is equivalent to:

short x = 3;
x = (short)(x + 4.6);


这也解释了为什么以下代码编译:

This also explains why the following code compiles:

byte b = 1;
int x = 5;
b += x; // compiles fine!

但这不是:

byte b = 1;
int x = 5;
b = b + x; // DOESN'T COMPILE!

在这种情况下你需要明确投出:

You need to explicitly cast in this case:

byte b = 1;
int x = 5;
b = (byte) (b + x); // now it compiles fine!






值得注意的是复合赋值中的隐式转换是精彩的书籍 Java Puzzlers Puzzle 9:Tweedledum 的主题> 。以下是本书的一些摘录(为了简洁而略微编辑):


It's worth noting that the implicit cast in compound assignments is the subject of Puzzle 9: Tweedledum from the wonderful book Java Puzzlers. Here are some excerpt from the book (slightly edited for brevity):


许多程序员认为 x + = i ; 只是 x = x + i; 的简写。这不完全正确:如果结果的类型比变量的类型宽,则复合赋值运算符执行静默缩小基元转换。

Many programmers think that x += i; is simply a shorthand for x = x + i;. This isn't quite true: if the type of the result is wider than that of the variable, the compound assignment operator performs a silent narrowing primitive conversion.

避免不愉快惊喜,不要对类型为 byte short 的变量使用复合赋值运算符,或者。在类型 int 的变量上使用复合赋值运算符时,请确保右侧的表达式不是 long float ,或 double 。在类型为 float 的变量上使用复合赋值运算符时,请确保右侧的表达式不是 double 。这些规则足以阻止编译器生成危险的缩小强制转换。

To avoid unpleasant surprises, do not use compound assignment operators on variables of type byte, short, or char. When using compound assignment operators on variables of type int, ensure that the expression on the right-hand side is not of type long, float, or double. When using compound assignment operators on variables of type float, ensure that the expression on the right-hand side is not of type double. These rules are sufficient to prevent the compiler from generating dangerous narrowing casts.

对于语言设计者来说,复合赋值运算符生成隐形强制转换可能是一个错误。复合赋值,其中变量的类型比计算结果的类型更窄应该是非法的。

For language designers, it is probably a mistake for compound assignment operators to generate invisible casts; compound assignments where the variable has a narrower type than the result of the computation should probably be illegal.

最后一段值得注意:在这方面,C#要严格得多(参见 C#语言规范7.13.2复合赋值)。

The last paragraph is worth noting: C# is a lot more strict in this regard (see C# Language Specification 7.13.2 Compound assignment).

这篇关于不同的行为可能会导致精度下降的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆