为什么0的0次方等于NaN(非数字)呢?

常用的数是十进制数^2+510的1次方+710^0表示十进制的数要用10个数码又叫数字在电子计算器用的二进制只需要两个数码零和一如二进制中110=12^2+12^1+02^0等于十进制的数^5+12^4+02^3+12^2+02^1+12^0=十进制的数53,那么二进制中的数101011=十进制中的哪个数?

}

之前陆陆续续写了很多架构、设计、思想、组织方向的文字,突然感觉到有些厌烦。因为笔者不断看到有些程序员“高谈阔论、指点江山”之余,各种定律、原则、思想似乎都能信手拈来侃侃而谈,辩论的场合就更喜欢扯这些大旗来佐证自己的"金身"。殊不知,这些人的底座脆弱到不堪一击,那些“拿来”的东西都是空中楼阁罢了。优秀程序员区别于其他的一项重要指标,就是基础知识的底蕴足够强大。靠看靠学靠实战靠日积月累,绝无捷径。

而今天要讲的"浮点运算"绝对是不少程序员知其表不知其内的一个知识点,甚至在某些人的编程世界里已经慢慢沦为鸡肋。比如在涉及精度必须准确的货币类财务运算中,要不更换单位*100转为Integer,要不使用BigDecimal,稍微有点"经验"的人这里都不会敢用Float/Double。

这里的“经验”指的是那种有一定的编程经验,但是理论知识结构有死角,在FP这个场景就是知道FP有精度丢失问题,但不知道为什么的那一类。

有人会问既然精度不准那浮点数还有什么价值, 直接用精度不会丢失的Integer或者BigDecimal就好了呗?这其实就是在数据精度、数值范围、运算速度之间的一个权衡,浮点数可表示的数值范围远大于整型,浮点数的运算速度也快于BigDecimal(现代的CPU都会集成FPU浮点运算单元)。在很多软件系统的实现里不用浮点数确实没问题,但是在一些游戏引擎、工程处理甚至天体物理方面的超大型数据运算,为了快速得到结果也防止数据范围溢出,只要误差在可接受范围内,浮点数当然可以是首选。

A.在 -pi/4 到 pi/4 的区间内,Java使用硬件级sin和cos函数,因此它们与C的时间大致相同。超出此区间的参数必须通过模数pi转换到此区间内。正如James Gosling在x87平台上的博客一样,硬件sin和cos使用近似值,这使得计算速度很快,但它并达不到IEEE要求的准确度。C实现会对所有参数使用硬件级sin和cos,牺牲速度以换取IEEE的一致性。

原文文末还有大量的练习题(可点击原文查看),有兴趣的同学一定要亲自去做做,对于理解上面大段理论有极大益处,顺带不要忘记篇首的几个知识点哟。当然如果对进制转换和精度舍入等等原理都已吃透,这些问答和练习题都不在话下。

古人云“格物致知”, 就是要我们穷究事物的真理达到知其然知其所以然的通透感,想来必是极好的。

- 致“天上飘着”的程序员们

(读者若是同时了解大学、朱熹、王阳明各种思想的神人,可能对这个词有不同见解,咱不在这辩论。反正现代汉语词典解释的是:研究事物原理而获得知识。语出《礼记·大学》:欲诚其意者,先致其知,致知在格物)

}

学过JavaScript的童鞋应该非常清楚,0.1 + 0.2 是不等于0.3的,而是等于0.00004,至于为什么会这样?好像有点说不清楚,只知道是JavaScript精确度

已经很久没有写技术文章了,脑袋瓜有点生锈,写的不好别见怪,今天就是想带点干货给大家分享一下。文章的内容有一点点难度,不过基本都是计算机组成原理的知识,算是温故而知新吧!

学过JavaScript的童鞋应该非常清楚,0.1 + 0.2 是不等于0.3的,而是等于0.00004,至于为什么会这样?好像有点说不清楚,只知道是JavaScript精确度问题,其他不得而知了。没关系,看完慢慢就懂了!

说明:转换过程就不在这边描述了

IEEE二进制浮点数算术标准(IEEE 754)是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用。
这个标准定义了表示浮点数的格式(包括负零-0)与反常值(denormal number)),一些特殊数值(无穷(Inf)与非数值(NaN)),以及这些数值的“浮点数运算符”;它也指明了四种数值舍入规则和五种例外状况(包括例外发生的时机与处理方式)。

上图是64位的双精度浮点数,最高位是符号位S(sign),中间的11位是指数E(exponent),剩下的52位为尾数(有效数字)M(mantissa)。

根据IEEE 754标准,任意一个浮点数的二进制都可以用如下公式进行表示:

S为符号位:表示浮点数的正负(0代表正数,1代表负数);

E为指数位:存储指数,该数都会加上一个常数(偏移量),用来表示次方数;

M为尾数位:表示有效位(尾数),超出的部分自动进1舍0;

双精度的浮点数真值(带有正负号的数值是真值)最终可以表示为:

说明:E是无符号整数,长度是11位,取值范围是为0~2047。因为科学计数法中的指数是可以为负数,所以约定减去一个中间数(偏移量)1023,[0,1022] 表示为负,[1024,2047] 表示为正。

大部分二进制浮点数都以规格化格式进行存放,以便将有效数字的精度最大化,提升精确度。

小数点向右移动4位,让其小数点左边只有一个“1”。

根据IEEE754标准,双精度浮点的尾数只能存储52位,红色的“1”是第53位,根据进1舍0的原则进行操作,操作后的值为:

指数-4等于1019(E) – 1023(常量),由此可得E等于1019,把1019转为二进制。

说明:红色为符号位;绿色为指数位;蓝色为尾数位;

小数点向右移动3位,让其小数点左边只有一个“1”。

红色的“1”是第53位,根据进1舍0的原则进行操作,操作后的值为:

指数-3等于1020(E) – 1023(常量),由此可得E等于1020,把1020转为二进制。

说明:红色为符号位;绿色为指数位;蓝色为尾数位;

对阶的目的是使两数的小数点位置对齐,方便两数进行运算,换句话说就是两数的阶码要相等。根据小阶向大阶看齐的原则,应使0.1的尾数向右移动1位(可以理解为小数点向左移动1位),阶码加1。

尾数向右移动1位后,阶码和尾数的值变化如下:

蓝色的“1”是右移补的位,红色的0是舍去的位,根据IEEE 754标准双精度浮点的尾数只能存储52位,遵循进1舍0的原则进行操作。

0.1的科学计数法表示:

0.1的二进制存储格式:

尾数部分M通常都是规格化表示的,非"0"的尾数其第1位总是"1",而这一位也称作隐藏位,因为存储的时候该位会被省略。比如存储1.0110时,只存储尾数0110,等到读取的时候才把第1位的1加补上去,这么做相当于多保存了1位有效数字。

根据尾数求和的结果,进行规格化处理,即尾数向右移1位,阶码加1。

尾数只能存储52位,红色的“1”需要舍去,根据进1舍0的原则进行操作可得:

指数-2等于1021(E) – 1023(常量),由此可得E等于1021,把1021转为二进制;

浮点数的溢出其实是阶码的溢出表现出来的,在算术运算过程中要检查是否产生了溢出。若阶码正常,算术运算正常结束;若阶码溢出,则要进行相应处理。

如上求和结果的阶码为,没有产生溢出,因此运算结束。

二进制存储格式是计算机存储和运算的格式,此时把二进制转为十进制,我们可以看看最终求和的值会是多少?

规格化的值是转为非规格化

指数的值为2,将规格化的小数点向左移动2位即可。

非规格化的值转成十进制

为了方便大家学习与实践,提供如下PHP实践代码,它是将“0.110100”转成十进制的功能代码,大家可以尝试测试一下。

好了,干货分享完毕,谢谢大家!

}

我要回帖

更多关于 12的0次方等于多少 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信