Java高级谜题87:紧张的关系

Java高级谜题87:紧张的关系,第1张

Java高级谜题87:紧张的关系,第2张

在数学中,等号(=)定义了实数之间的等价关系。这种等价关系将一个集合分成许多等价类,每个等价类由所有彼此相等的值组成。其他等价关系包括所有三角形集合上的同余关系和所有书籍集合上的相同页数关系。事实上,关系~是等价关系当且仅当它是自反的、传递的和对称的。这些性质定义如下:
自反性:对于所有x,x ~ x .换句话说,每个值都与自身有关系。
传递性:如果x ~ y,y ~ z,那么x ~ z .也就是说,如果第一个值与第二个值相关,第二个值与第三个值相关,那么第一个值与第三个值相关。
对称性:如果x ~ y,那么y ~ x .也就是说,如果第一个值和第二个值有关系~,那么第二个值和第一个值也有关系~。
如果你看了难题29,就可以知道运算符= =不是自反的,因为表达式(Double。NaN == Double。NaN)为假,表达式(Float)也是。NaN == Float。南)。但是算符= =违反对称性和传递性吗?其实并不违反对称性:对于x和y的所有值,(x == y)表示(y == x)。传递性完全是另一回事。难题35为operator = =作用于原类型的数值时不符合传递性的原因提供了线索。当比较两个原始类型值时,运算符= =首先执行二进制数值提升[JLS 5.6.2]。这将导致这两个值中的一个进行扩大的原始转换。大多数原始类型转换不会有问题,但有三个值得注意的例外:当int或long值转换为float值,或long值转换为double值时,精度将会丢失。这种精度的损失可以证明= =运算符是不可传递的。
实现这种不可传递性的诀窍是用上面三个数值比较中的两个来损失精度,然后就可以得到相反的结果。可以这样构造一个例子:给X和Z赋两个大但不同的长值,给y赋一个类似于前两个长值的double值,下面的程序是它的代码,它打印出来的结果是true true false,很明显证明了运算符= =作用于原类型时是不可传递的。
public class Transitive {
public static void main(String[]args)抛出异常{
long x = Long。MAX _ VALUE
double y = (double) Long。MAX _ VALUE
long z = Long。MAX _ VALUE-1;
system . out . print((x = = y)+" ");//不严谨!
system . out . print((y = = z)+" ");//不严谨!
system . out . println(x = = z);//精确!
}
}

这个谜题的教训是:警惕扩大float和double类型的原类型转换带来的损失。他们沉默,但却致命。它们将违背你的直觉,并可能导致非常微妙的错误(见难题34)。更一般地说,要警惕那些混合类型的操作(谜题5、8、24和31)。这个难题给语言设计者上了和难题34一样的一课:准确性的无声丧失让程序员困惑。

位律师回复
DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
白度搜_经验知识百科全书 » Java高级谜题87:紧张的关系

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情