谜题29:循环者的新娘

请提供一个对i的声明,将下面的循环转变为一个无限循环:


while (i != i) {

}

这个循环可能比前一个还要使人感到困惑。不管在它前面作何种声明,它看起来确实应该立即终止。一个数字总是等于它自己,对吗?

对,但是IEEE 754浮点算术保留了一个特殊的值用来表示一个不是数字的数量[IEEE 754]。这个值就是NaN(“不是一个数字(Not a Number)”的缩写),对于所有没有良好的数字定义的浮点计算,例如0.0/0.0,其值都是它。规范中描述道,NaN不等于任何浮点数值,包括它自身在内[JLS 15.21.1]。因此,如果i在循环开始之前被初始化为NaN,那么终止条件测试(i != i)的计算结果就是true,循环就永远不会终止。很奇怪但却是事实。

你可以用任何计算结果为NaN的浮点算术表达式来初始化i,例如:


double i = 0.0 / 0.0;

同样,为了表达清晰,你可以使用标准类库提供的常量:


double i = Double.NaN;

NaN还有其他的惊人之处。任何浮点操作,只要它的一个或多个操作数为NaN,那么其结果为NaN。这条规则是非常合理的,但是它却具有奇怪的结果。例如,下面的程序将打印false:


class Test {

   public static void main(String[] args) {

       double i = 0.0 / 0.0;

       System.out.println(i - i == 0);

   }

}

这条计算NaN的规则所基于的原理是:一旦一个计算产生了NaN,它就被损坏了,没有任何更进一步的计算可以修复这样的损坏。NaN值意图使受损的计算继续执行下去,直到方便处理这种情况的地方为止。

总之,float和double类型都有一个特殊的NaN值,用来表示不是数字的数量。对于涉及NaN值的计算,其规则很简单也很明智,但是这些规则的结果可能是违背直觉的。

原文地址:https://www.cnblogs.com/yuyu666/p/9840452.html

时间: 2024-08-29 17:31:16

谜题29:循环者的新娘的相关文章

C#解惑29: 循环者的新娘

谜题29: 循环者的新娘 请提供一个对i的声明,将下面的循环转变为无限循环: while (i != i) { } 解惑29: 循环者的新娘 这个循环可能比前一个更令人困惑.不管在它前面作何种声明,它看起来确实应该立即终止.一个数字总是等于它自己,对吧? 对,但IEEE 754浮点算术保留了一个特殊的值用来表示一个不是数字的数量.这个值就是NaN("Not a Number(不是一个数字)"的缩写),对于所有没有良好的数字定义的浮点计算,例如0.0/0.0,其值都是它.规范中描述道,N

Java解惑三:循环之谜

谜题24 byte是有符号的,范围是-128 - 127.而0x90是int类型.比较的时候,不相等. 如果想让其相等,需要进行类型转换:(byte & 0xff) 或者 (byte)0x99. 谜题25 自增运算符对循环的影响.j = j++,先赋值. 谜题26 Integer.MAX_VALUE加一之后会变成Integer.MIN_VALUE,这对循环会有影响. 可以考虑使用long来表示i变量,或者使用效率更高的i != Integer.MAX_VALUE. 谜题27 (-1 <<

C#解惑30: 循环者的爱子

谜题30: 循环者的爱子 请提供一个对i的声明,将下面的循环转变为一个无限循环: while (i != i + 0) { } 与前一个谜题不同,你必须在答案中不使用浮点数.换句话说,你不能把i声明为double或float类型. 解惑30: 循环者的爱子 与前一个谜题一样,这个谜题初看起来是不可能实现的.毕竟,一个数字总是等于它自身加上0,你被禁止使用浮点数,因此不能使用NaN.而在整数类型中没有NaN的等价物.那么,你能给出什么呢? 我们必然可以得出这样的结论,即i的类型必须是非数值类型的,

Map集合遍历的四种方式理解和简单使用-----不能for循环遍历

~Map集合是键值对形式存储值的,所以遍历Map集合无非就是获取键和值,根据实际需求,进行获取键和值 1:无非就是通过map.keySet()获取到值,然后根据键获取到值 for(String s:map.keySet()){            System.out.println("key : "+s+" value : "+map.get(s));     } 2:通过Map.Entry(String,String) 获取,然后使用entry.getKey(

《Java解惑》读书笔记

 摘选自<Java解惑>一书,之前整理了部分,一直没看完,最近为了督促自己每天读点这本书,决定一天至少更新一个谜题的内容,欢迎讨论. 欢迎关注技术博客http://blog.sina.com.cn/u/1822488043 Java解惑读书笔记 谜题1:奇数性 取余操作的定义: ( a / b ) * b + ( a % b ) = a 其中(a/b)是java运算的结果,也就是a/b是一个整数,比如3/2=1. 所以当取余操作返回一个非零结果的时候,它与左操作数具有相同符号. 请测试你的

Java常见问题3:周期之谜

谜24 byte是有符号的.范围是-128 - 127. 而0x90是int类型. 比較的时候.不相等. 假设想让其相等,须要进行类型转换:(byte & 0xff) 或者 (byte)0x99. 谜题25 自增运算符对循环的影响.j = j++,先赋值. 谜题26 Integer.MAX_VALUE加一之后会变成Integer.MIN_VALUE.这对循环会有影响. 能够考虑使用long来表示i变量,或者使用效率更高的i != Integer.MAX_VALUE. 谜题27 (-1 <&l

java解惑之陷阱和缺陷的目录总结

A1 词汇问题 A 1.1 字母l在许多字体中都与数字1相像 规则:在long类型字面常量中,应该总是用大写L,千万不要用小写l.不要用孤零零的一个l作为变量名. 谜题4 A 1.2 负的十六进制字面常量看起来像正的 规则: 要避免混合类型的计算.在恰当的地方要用long类型的字面常量代替int类型的字面常量.谜题5 A 1.3 八进制字面常量与十进制字面常量相像 规则: 要避免八进制字面常量.如果非得使用它们,那么请对所有用到的地方进行注释,以使得你的意图清晰. 谜题59 A 1.4 ASCI

projecteuler Summation of primes

The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. Find the sum of all the primes below two million. 译文: 10以下的素数之和为17,求出2000000以下的素数之和. ======================= 第一次code: 1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(

AOJ 756.电梯

电梯 Time Limit: 1000 ms   Case Time Limit: 1000 ms   Memory Limit: 64 MBTotal Submission: 21   Submission Accepted: 13 Description 在城市的高层建筑物中,只有一部电梯,由N个正整数组成一个请求列表,列表中的数字表示电梯将在哪层停,电梯按列表顺序依次停靠.电梯每上行一层需要花6秒时间,每下行一层需要花4秒时间,电梯每停一次需要用时5秒.对于给定的请求列表,计算完成所有请求