在控制台输入0.1+0.2,会得出以下结果

即不等于0.3。下面我们说一下原因。

一、存储原理

1.在计算机中数字无论是定点数还是浮点数都是以多位二进制的方式进行存储的。
2.在JS中数字采用的IEEE 754的双精度标准进行存储(存储一个数值所使用的二进制位数比较多,精度更准确)。

二、示例

在定点数中,如果我们以8位二进制来存储数字。
对于整数来说,十进制的35会被存储为: 00100011 其代表 2^5 + 2^1 + 2^0。
对于纯小数来说,十进制的0.375会被存储为: 0.011 其代表 1/2^2 + 1/2^3 = 1/4 + 1/8 = 0.375
对于像0.1这样的数值用二进制表示你就会发现无法整除,最后算下来会是 0.000110011…由于存储空间有限,最后计算机会舍弃后面的数值,所以我们最后就只能得到一个近似值
JS中采用的IEEE 754的双精度标准也是一样的道理在存储空间有限的情况下,当出现这种无法整除的小数的时候就会取一个近似值,在js中如果这个近似值足够近似,那么js就会认为他就是那个值。

console.log(0.1000000000000001)
// 0.1000000000000001 (中间14个0,会打印出本身)
console.log(0.10000000000000001)
// 0.1 (中间15个0,js会认为两个值足够近似,所以输出0.1)

由于0.1转换成二进制时是无限循环的,所以在计算机中0.1只能存储成一个近似值。
另外说一句,除了那些能表示成 x/2^n 的数可以被精确表示以外,其余小数都是以近似值得方式存在的。
在0.1 + 0.2这个式子中,0.1和0.2都是近似表示的,在他们相加的时候,两个近似值进行了计算,导致最后得到的值是0.30000000000000004,此时对于JS来说,其不够近似于0.3,于是就出现了0.1 + 0.2 != 0.3 这个现象。当然,也并非所有的近似值相加都得不到正确的结果。

三、解决方法

方式一: 想办法规避掉这类小数计算时的精度问题就好了,那么最常用的方法就是将浮点数转化成整数计算。因为整数都是可以精确表示的。

0.1+0.2 => (0.1*+0.2*)/

方式二 : js的Number对象有一个保留小数位数的方法:toFixed();传入一个需要保留的位数就OK:

(0.1+0.2).toFixed()==0.3

注:JS的小数点精确到第16位。

JS中0.1+0.2!=0.3的更多相关文章

  1. 在js中做数字字符串加0补位,效率分析

    分类: Jquery/YUI/ExtJs 2010-08-30 11:27 2700人阅读 评论(0) 收藏 举报 functiondate算法语言c 通常遇到的一个问题是日期的“1976-02-03 ...

  2. 在js中做数字字符串补0

    转自(http://blog.csdn.net/aimingoo/article/details/4492592) 通常遇到的一个问题是日期的“1976-02-03 HH:mm:ss”这种格式 ,我的 ...

  3. js中setTimeout() 时间参数为0

    当看到下面 这种setTimeout 设置为0 写法的时候一脸懵逼,完全没用过. var fuc = [1,2,3]; for(var i in fuc){ setTimeout(function() ...

  4. java、js中实现无限层级的树形结构(类似递归)

    js中: var zNodes=[ {id:0,pId:-1,name:"Aaaa"}, {id:1,pId:0,name:"A"}, {id:11,pId:1 ...

  5. js中要声明变量吗?

    你好,js语言是弱类型语言,无需申明即可直接使用,默认是作为全局变量使用的.建议:在function里时应使用var 申明变量,这样改变量仅仅只在function的生存周期内存在,不会污染到,全局控件 ...

  6. 在JS中关于堆与栈的认识function abc(a){ a=100; } function abc2(arr){ arr[0]=0; }

    平常我们的印象中堆与栈就是两种数据结构,栈就是先进后出:堆就是先进先出.下面我就常见的例子做分析: main.cpp int a = 0; 全局初始化区 char *p1; 全局未初始化区 main( ...

  7. 字符串0.在php和js中转换为布尔类型 值是false还是true

    在php 中 $a = '0'; $b = (bool)$a; var_dump($a);//输出false 在js中官方说明: Note:If the value parameter is omit ...

  8. js中的0就是false,非0就是true及案例

    在处理js代码判断真假时经常会这么写. 但fun()可能得到的是数字0,这可不是表示的没有值,但是!js中的数字0就是false,非0就是true. 于是0就被无情的当做false了. 已经被这个坑过 ...

  9. 深入理解 Node.js 中 EventEmitter源码分析(3.0.0版本)

    events模块对外提供了一个 EventEmitter 对象,即:events.EventEmitter. EventEmitter 是NodeJS的核心模块events中的类,用于对NodeJS中 ...

  10. 为什么js中要用void 0 代替undefined

    这个是Backbone.js中的一句源码 if (callback !== void 0 && 'context' in opts && opts.context == ...

随机推荐

  1. JDK源码之String类解析

    一 概述 String由final修饰,是不可变类,即String对象也是不可变对象.这意味着当修改一个String对象的内容时,JVM不会改变原来的对象,而是生成一个新的String对象 主要考虑以 ...

  2. Nacos 配置MySQL8.0持久化

    问题描述 官网下载的Nacos mysql由于驱动过低只支持5.X版本,使用8.X版本的mysql时无法正常启动 解决办法 克隆nacos源码(branch 1.0.0-RC3) master等分支也 ...

  3. C语言创建文件夹

    问题需求:在程序中需要使用文件夹时,一般可以先在程序目录或某一路径下创建一个文件夹,然后使用该文件夹. 这种方法比较麻烦,需提前创建文件夹. 使用C语言创建文件夹的代码可以如下: #include & ...

  4. vue-particles做背景,鼠标动画粒子连线填坑(按钮没有点击响应)

    为了提高页面展示效果,登录界面内容比较单一的,粒子效果作为背景经常使用到,vue工程中利用vue-particles可以很简单的实现页面的粒子背景效果. 解决问题: 以背景方式显示 无法获取按钮焦点, ...

  5. printf的用法进阶

    今天来好好总结一下C语言中关于printf的常用用法 基础部分 printf("%d\n", numInt); printf("%f\n", numFloat) ...

  6. 从零开始学习redis源码

    2020的开年是比较艰难的,爆发了肺炎疫情,希望大家多注意安全,也希望疫情早日好转! 以3.2版本的源码为例,开始讲解,有时会贴出源码,进行说明,并会注明源码出处. 数据库 应该都知道默认redis会 ...

  7. WeChall_PHP 0817 (PHP, Exploit)

    I have written another include system for my dynamic webpages, but it seems to be vulnerable to LFI. ...

  8. Go语言实现:【剑指offer】字符串的排列

    该题目来源于牛客网<剑指offer>专题. 输入一个字符串,按字典序打印出该字符串中字符的所有排列.例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,b ...

  9. 一文带你了解 C# DLR 的世界

    一文带你了解 C# DLR 的世界 在很久之前,我写了一片文章dynamic结合匿名类型 匿名对象传参,里面我以为DLR内部是用反射实现的.因为那时候是心中想当然的认为只有反射能够在运行时解析对象的成 ...

  10. php curl 检测网页是否被百度收录

    <?php /* * 检测百度是否收录网页 curl模式 * @ param string $url传入的url* return int (1 收录 0 不收录) */ function che ...