引言
我们都知道计算机是用二进制表示数据,那浮点数计算机是怎么表示的那?
1.0/0的结果是什么?为什么?
0/0的结果是什么?为什么?
0.0/0.0的结果是什么?为什么?
先说结论:
1)1.0/0的结果是什么?为什么?
1.1 结果:Infinity
1.2 原因:①1/0.1=10 ②1/0.01=100 ③1/0.001=1000,所以分子确定时,分母越小商越大,分母趋向于0时,商无穷大。对于java语言,手册中也有提到加减运算的第一步就是零值检测,如果涉及其中一个数是0,可以直接得出结果。
2)0/0的结果是什么?为什么?
2.1 结果:Exception / by zero
2.2 原因:根据乘法与除法互为逆运算可证,一是零做除数不能得到固定的商;二是零做除数还不回原。因此说:“零做除数没有意义”或“规定零不能做除数”。1)中提到的java语言可适用
3)0.0/0.0的结果是什么?为什么?
3.1 结果:NaN
3.2 原因:个人觉得还是java虚拟机自己搞的逻辑,目的就是用一个公式来模拟出这种Not a Number的值来,就像NaN转成Long统一翻译为0xff800001一样。底层应该是在零值检测时处理的。为什么这样说,因为(0.0f == 0)是true,那0.0/0是不是就等于0/0,那为什么会有两种结果。只有自己定义用来标示能解释通的吧。
NaN是什么?
NaN是“IEEE 754”协议中规定了几种特殊值,
1. 第一种 指数是0并且尾数的小数部分是0,这个数±0(和符号位相关)
2. 第二种 指数2e-1并且尾数的小数部分是0,这个数是±∞(同样和符号位相关)
3. 第三种 指数2e-1并且尾数的小数部分非0,这个表示为不是一个数(NaN)
这些方法也就对应了计算机内部的存储,相对应的就是jdk中native longBitsToDouble()方法中
<p>If the argument is any value in the range {@code 0x7f800001} through {@code 0x7fffffff} or in the range {@code 0xff800001} through {@code 0xffffffff}, the result is a NaN.</p>
<p>If the argument is {@code 0x7f800000}, the result is positive infinity.
<p>If the argument is {@code 0xff800000}, the result is negative infinity.
在计算机中归根结底都是要通过0 1来表示,只不过定义的区间不同罢了,java中对NaN用一个Long型值表示 0x7fc00000,具体可参见JDK intBitsToFloat()方法,将一定区间内的值,转化为一个常量值。
NaN是怎么产生的?
NaN的产生还是要通过数学来求证,数学中求这个公式的值x/[x*cos(1/x)],当x趋向于0的时候,利用洛必达法则可推导出这个公式的结果是不存在的,因为cos(1/x)的极限不存在,所以上下不能比较。在代码中乘除的运算都是对应的加减被除数,《码出高效:java开发手册》中提到,加减运算是第一步就是零值检测,检查参加运算是否存在为0的数。
推测java虚拟机就是在这一步进行的处理,python中使用0.0/0.0会的到一个ZeroDivisionError: float division by zero,并不是NaN,这样表示float('nan')的时候才会提示NaN。
触发的情况
1. 至少有一个参数是NaN的运算
2. 不定式
2.1 下列除法运算:0/0、∞/∞、∞/−∞、−∞/∞、−∞/−∞
2.2 下列乘法运算:0×∞、0×−∞
2.3 下列加法运算:∞ + (−∞)、(−∞) + ∞
2.4 下列减法运算:∞ - ∞、(−∞) - (−∞)
3. 产生复数结果的实数运算。例如:
3.1 对负数进行开偶次方的运算
3.2 对负数进行对数运算
3.3 对正弦或余弦到达域以外的数进行反正弦或反余弦运算