最近又一次看到这个问题,想起那句话,铁打的营盘流水的兵,程序界也是一样,当年c语言的题目问了java,再问js,老的一辈知道了再问小年轻。可是基础就是这种你不能不会的东西,希望今天的文章能够将这个问题讲的能让年轻的人知道原因。
在调试器中,我们写出0.1+0.2的诗句,按下回车,调试器告诉你,答案是0.30000000000000004,“你错了”,你对调试器说,“没有”,调试器理直气壮的回答你。“你就是错了”,“没有没有!”,你气的打开电脑终端,询问他是谁错了,“是你错了,而且,这就是你没有对象的原因”,你还是不服,“你们都是js,我要问问python,于是你又在python环境下打下这行诗句,他任然告诉你,js没错”。
“这就是你没有对象的原因?”,你惊呆了,你一定要弄清楚这原因是什么,毕竟已经闹这一出了。
带着些许恼怒些许担忧,你找到了大师。大师说:你先和js干起来的,咱们就先说说js吧,如果你写下的诗句不是0.1+0.2,而是1+2,那么谁都不会反对你让它等于3。错就错在你写的是小数,因为在js中,Number类型的标准是ECMA的标准,也就是IEEE 754的双精度数值,这一类数值就是通常java中所说的double类型,而这一标准就是通用的一个对实数进行计算机编码的标准。所以,不光是js,python,java等编程语言大家都是这样认为。
回到标准上来,不管是人还是计算机,我们需要知道“1是1”,就要对“1”编码,我们用“1”去描述“1”,是因为我们知道“1”就是代表“1”。就是因为这一点,我们和计算机沟通上就有了一些隔阂了,因为他天生不懂“1”代表“1”,就像老外不懂汉语一样。我们以为告诉了计算机一个十进制的数字,实际上计算机把它转换成二进制存起来了,保留的时候会进行位数限定。浮点数和浮点数相加的时候就存在误差了。就像外国人翻译古诗之后再翻译成中文就不好听了一样,十进制小数转换成二进制存在计算机中只能无限近似,在涉及到运算,就更加会有误差了。因此,对于小数的运算,一般是转换成整数运算,然后在转换回去。
所以,有一些用心的前辈整理了一些浮点数原则:
1.尽量不用小数,货币使用最小单位,避免使用除法,用了,也要尽可能转换成整数。
2.引入多于计算要求的小数位,在计算时多增加几位小数。
3.使用isFinite()和isNaN()保证合法性。
4.计算越少越好。
现在你懂了?
懂了,可是,这和找不到对象也没关系吧。
“说语言错误那是你不懂语言,你不懂语言你就不懂计算机。说女人错误说明你不懂女人。”
“我没说女人错误呀。”