理解JavaScript的浮点数

大多数编程语言都有几种数值型数据类型,但是JavaScript却只有一种。你可以使用typeof 运算符查看数字的类型。不管是整数还是浮点数,JavaScript都将它们简单地归类为数字。

typeof 17;  //number
typeof 98.6; //number
typeof -21.3; //number

事实上,JavaScript中所有的数字都是双精度浮点数。这是由IEEE754标准制定的64位编码数字——即“doubles”。如果这一事实使你疑惑JavaScript是如何表示整数的,请记住,双精度浮点数能完美地表示高达53位精度的整数。从–9 007 199 254 740 992(–253)到9 007 199 254 740 992(253)的所有整数都是有效的双精度浮点数。因此,尽管JavaScript中缺少明显的整数类型,但是完全可以进行整数运算。

大多数的算术运算符可以使用整数、实数或两者的组合进行计算。

0.1 * 0.9;  //0.19
-99 + 100; //1
21- 12.3; //8.7
2.5 /5; //0.5
21%8; //5

然而位算术运算符比较特殊。JavaScript不会直接将操作数作为浮点数进行运算,而是会将其隐式地转换为32位整数后进行运算。(确切地说,它们被转换为32位大端(big-endian)的2的补码表示的整数。)以按位或运算表达式为例:

8|1;  //9

看似简单的表达式实际上需要几个步骤来完成运算。如前所述,JavaScript中的数字8和1都是双精度浮点数。但是它们也可以表示成32位整数,即32位0、1的序列。整数8表示为32位二进制序列如下所示:

00000000000000000000000000001000

你自己也可以使用数字类型的toString方法来查看:

(8).toString(2)  //"1000"

toString方法的参数指定了其转换基数,此例子以基数2(即二进制)表示。结果值省略了左端多余的0(位),因为它们并不影响最终值。

整数1表示为32位二进制如下所示:

00000000000000000000000000000001

按位或运算表达式合并两个比特序列。只要参与运算的两位比特中任意一位为1,运算结果的该位就为1。以位模式表示的结果如下:

00000000000000000000000000001001

这个序列表示整数9。你可以使用标准的库函数parseInt验证,同样以2作为基数:

parseInt("1000", 2); //9

(同样,前导0位是不必要的,因为它们并不影响运算结果。)

所有位运算符的工作方式都是相同的。它们将操作数转换为整数,然后使用整数位模式进行运算,最后将结果转换为标准的JavaScript浮点数。一般情况下,JavaScript引擎需要做些额外的工作来进行这些转换。因为数字是以浮点数存储的,必须将其转换为整数,然后再转换回浮点数。然而,在某些情况下,算术表达式甚至变量只能使用整数参与运算,优化编译器有时候可以推断出这些情形而在内部将数字以整数的方式存储以避免多余的转换。

关于浮点数的最后警示是,你应该对它们保持时刻警惕。浮点数看似熟悉,但是它们是出了名的不精确。甚至一些看起来最简单的算术运算都会产生不正确的结果。

0.1+0.2; 0.300000000000004

尽管64位的精度已经相当高了,但是双精度浮点数也只能表示一组有限的数字,而不能表示所有的实数集。浮点运算只能产生近似的结果,四舍五入到最接近的可表示的实数。当你执行一系列的运算,随着舍入误差的积累,运算结果会越来越不精确。舍入也会使我们通常所期望的算术运算定律产生一些出人意料的偏差。例如,实数满足结合律,这意味着,对于任意的实数x,y,z,总是满足(x + y) + z = x + (y + z)。

然而,对于浮点数来说,却并不总是这样。

(0.1+0.2)+0.3;  //0.60000000000000001
0.1+(0.2+ 0.3); //0.6

浮点数权衡了精度和性能。当我们关心精度时,要小心浮点数的局限性。一个有效的解决方法是尽可能地采用整数值运算,因为整数在表示时不需要舍入。当进行货币相关的计算时,程序员通常会按比例将数值转换为最小的货币单位来表示再进行计算,这样就可以以整数进行计算。例如,如果上面的计算是以美元为单位,那么,我们可以将其转换为整数表示的美分进行计算。

(10+20)+30; //60
10+ (20+30); //60

对于整数运算,你不必担心舍入误差,但是你还是要当心所有的计算只适用于–253~253的整数。

提示

  1. JavaScript的数字都是双精度的浮点数。
  2. JavaScript中的整数仅仅是双精度浮点数的一个子集,而不是一个单独的数据类型
  3. 位运算符将数字视为32位的有符号整数。

4. 当心浮点运算中的精度陷阱。

系列文章导航:

1、你不知道的JavaScript–Item1 严格模式

2、你不知道的JavaScript–Item2 浮点数精度

3、你不知道的JavaScript–Item3 隐式强制转换

4、你不知道的JavaScript–Item4 基本类型和基本包装类型(引用类型)

5、你不知道的JavaScript–Item5 全局变量

6、你不知道的JavaScript–Item6 var预解析与函数声明提升(hoist )

7、你不知道的JavaScript–Item7 函数和(命名)函数表达式

8、你不知道的JavaScript–Item8 函数,方法,构造函数调用

9、你不知道的JavaScript–Item9 call(),apply(),bind()与回调

10、你不知道的JavaScript–Item10 闭包(closure)

11、你不知道的JavaScript–Item11 arguments对象

12、你不知道的JavaScript–Item12 undefined 与 null

13、你不知道的JavaScript–Item13 理解 prototype, getPrototypeOf 和_ proto_

14、你不知道的JavaScript–Item14 使用prototype的几点注意事项

15、你不知道的JavaScript–Item15 prototype原型和原型链详解

16、你不知道的JavaScript–Item16 for 循环和for…in 循环的那点事儿

17、你不知道的JavaScript–Item17 循环与prototype最后的几点小tips

18、你不知道的JavaScript–Item18 JScript的Bug与内存管理

19、你不知道的JavaScript–Item19 执行上下文(execution context)

20、你不知道的JavaScript–Item20 作用域与作用域链(scope chain)

21、你不知道的JavaScript–Item21 漂移的this


持续更新中……………….

版权声明:本文为小平果原创文章,转载请注明:http://blog.csdn.net/i10630226

你不知道的JavaScript--Item2 浮点数精度的更多相关文章

  1. 【读书笔记】-- 你不知道的JavaScript

    <你不知道的JavaScript>是一个不错的JavaScript系列书,书名可能有些标题党的意思,但实符其名,很多地方会让你有耳目一新的感觉. 1.typeof null === &qu ...

  2. 《你不知道的JavaScript》系列分享专栏

    <你不知道的JavaScript>系列分享专栏 你不知道的JavaScript”系列就是要让不求甚解的JavaScript开发者迎难而上,深入语言内部,弄清楚JavaScript每一个零部 ...

  3. [Effective JavaScript 笔记] 第2条:理解JavaScript的浮点数

    JavaScript数值型类型只有数字 js只有一种数值型数据类型,不管是整数还是浮点数,js都把归为数字. typeof 17;   // “number” typeof 98.6; // “num ...

  4. 关于JavaScript中计算精度丢失的问题

    摘要: 由于计算机是用二进制来存储和处理数字,不能精确表示浮点数,而JavaScript中没有相应的封装类来处理浮点数运算,直接计算会导致运算精度丢失. 为了避免产生精度差异,把需要计算的数字升级(乘 ...

  5. 《你不知道的JavaScript》整理(二)——this

    最近在读一本进阶的JavaScript的书<你不知道的JavaScript(上卷)>,这次研究了一下“this”. 当一个函数被调用时,会创建一个活动记录(执行上下文). 这个记录会包含函 ...

  6. 《你不知道的JavaScript》整理(一)——作用域、提升与闭包

    最近在读一本进阶的JavaScript的书<你不知道的JavaScript(上卷)>,里面分析了很多基础性的概念. 可以更全面深入的理解JavaScript深层面的知识点. 一.函数作用域 ...

  7. 你不知道的Javascript(上卷)读书笔记之一 ---- 作用域

    你不知道的Javascript(上卷)这本书在我看来是一本还不错的书籍,这本书用比较简洁的语言来描述Js的那些"坑",在这里写一些博客记录一下笔记以便消化吸收. 1 编译原理 在此 ...

  8. mingw fbx sdk /浮点数精度

    接下来要做一个linux下的程序了. 下载linux version     fbx sdk tar zxvf ...gz 按照安装说明 提升权限并没什么用 还是,cannot execute bin ...

  9. 你不知道的JavaScript上卷笔记

    你不知道的JavaScript上卷笔记 前言 You don't know JavaScript是github上一个系列文章   初看到这一标题的时候,感觉怎么老外也搞标题党,用这种冲突性比较强的题目 ...

随机推荐

  1. MySQL 5.6初始配置调优

    原文链接: What to tune in MySQL 5.6 after installation原文日期: 2013年09月17日翻译日期: 2014年06月01日翻译人员: 铁锚 随着 大量默认 ...

  2. iOS中动态计算不同颜色、字体的文字高度

    在改项目bug的时候,有一个问题动态计算label的高度,前开发者竟然用字符串长度除以14.16这样的常量来计算是否换行,结果cell的高度问题非常严重. 因为label内容里有部分关键字是要另一种颜 ...

  3. django-debug-tools 使用

    用django开发很快也很容易,但是很多时候我们的经验并不是很足,就会给自己挖下很多坑,不管是性能问题,还是开发语言使用技巧问题都会给应用的稳定带来危害, 开发之后的调试和调优就显得很重要,今天就尝试 ...

  4. 杭电ACM 1001题

    import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc=ne ...

  5. Windows平台安装及配置Hadoop(不借助cygwin)

    由于项目需要,我在VMware上装了几个虚拟机Windows server 2012 R2,并要搭建Hadoop集群.刚刚入门hadoop,一头雾水,然后开始搜各种教程,首先是选用cygwin进行安装 ...

  6. java集合框架--List、Set、Map

      1.List:有序的 collection(也称为序列).此接口可以对列表中每个元素的插入位置进行精确地控制.可以根据元素的在列表中的位置访问元素,并搜索列表中的元素.列表允许重复的元素.    ...

  7. Airbnb/Apache Superset – the open source dashboards and visualization tool – first impressions and link to a demo

    https://assemblinganalytics.com/post/airbnbapache-superset-first-impressions-and-link-to-a-demo/ Tod ...

  8. 接口和抽象类的区别(JDK1.8)

    1.一个类只能进行单继承,但可以实现多个接口. 2.有抽象方法的类一定是抽象类,但是抽象类里面不一定有抽象方法: 接口里面所有的方法的默认修饰符为public abstract,接口里的成员变量默认的 ...

  9. BigDecimal常用的加减乘除算法、比较大小、保存两位小数点

    项目中涉及到了BigDecimal的加.减.乘.比较大小.精确度的问题.所以在此总结一下,方便以后复习. //加法 BigDecimal coins = new BigDecimal("0& ...

  10. DUIR Framework 相关技术介绍

    开发者在搭建界面自动化测试框架时,又或者在开发界面自动化控制的机器人时,往往需要对界面进行自动化的程序控制.而现在公司内部使用的杜尔自动化框架,就是一个封装了界面自动化控制逻辑的程序框架.基于该框架, ...