为什么计算机编程语言中:0.1+0.2不等于0.3

最近在学习JS过程中发现在计算机JS时发现了一个非常有意思事,0.1+0.2的结果不是0.3,而是0.30000000000000004,但先将小数做乘法然后相加,再除回来就得到想要的0.3

我用python试了一下,发现python也是一样的,结果也是0.30000000000000004。

然后我开始信息搜集,最后找到了答案。想知道这其中的原因,要先理解这些点:二进制、指数形式、IEEE 754标准。

1、二进制

在计算机中所有的数据都是二进制形式存储的,包括整数、浮点数以及其他所有类型的数据。我们将十进制的0.1以及0.2转换成二进制

转换的方法也比较简单,整数转换成二进制:就是用整数除以2然后从下往上取余数,下图用100举例

然后小数转换成二进制就是,小数部分无限乘以2,然后顺序取整。下图用0.375举例

2、指数形式

用指数方式表示可以在有限的空间里存储更大的数值。

所有的十进制数都可以用指数形式表示,成为D=M*10E,比如100可以表示为1*102

二进制数也可以用指数形式表示,B=M*2E的形式,这里的E为指数,M为B的位数。比如0.011可以表示为1.1*10-10,这里的“-10”表示的是-2。

3、浮点数IEEE754标准

JavaScript中所有数字包括整数和小数都只有一种类型,是遵循 IEEE 754 标准,使用64位固定长度来表示,也就是标准的 double 双精度浮点数。

这里第一位为符号位“1”表示负数,“0”表示正数

一、首先将十进制的0.1转换成二进制:0.0011001100110011......

然后将十进制的0.2转换成二进制:0.0011001100110011........

二、将二进制的0.1和0.2转换成指数形式

十进制:0.1

二进制形式:0.000110011001100110011......

指数形式:1.10011001100110011......*2-100          //指数是-4

十进制:0.2

二进制形式:0.001100110011001100110011......

指数形式:1.100110011001100110011......*2-11     //指数是-3

三、将指数形式转换为IEEE754标准

这里由于IEEE754标准规定了尾数只能保留52位,所以无限循环小数需要做四舍五入,只保留52位小数(就是第53位以后全部舍弃,第53位“0舍1入”,而当第52位为1时,还得再进一位)

将十进制0.2转换成IEEE 754标准:

四、使用IEEE 754形式的 0.1+0.2

这块太长了,简单写的话应该就是10.0100100100100100100100100100100......100111,但是此时得到的数指数依然是指数形式,要将它转换成为二进制形式,就是将小数点向前移三位变成0.01001001001001001001001.....00111

然后将这个数转换为十进制数就是0*2-1+1*2-2+0*2-3+0*2-4.......+1*2-52之后就可以得到0.30000000000000004了

总结一下就是:

计算机存储数据时由于空间有限,所以只能存储固定长度的数据,而像一些无限循环的数据只能被四舍五入,所以一些数据可能会和它本身有一些误差,所以做相加运算也会有误差。

那么最后再看一下(0.1*10+0.2*10)/10为什么等于3,由于0.1和0.2先做乘法运算所以就变成了整数,所以再来看一下整数之间的加法。

最后再用3/10就得到了0.3,这个怎么算我还没琢磨,就直接计算器吧 -..-

原文地址:https://www.cnblogs.com/hai-long/p/12552148.html

时间: 2024-10-06 09:08:20

为什么计算机编程语言中:0.1+0.2不等于0.3的相关文章

Go编程语言中if...else语句的语法

在这四次救火中,举2个印象最深的例子,有一天晚上9点多,领导给我打电话说厦门某项目的系统今天下午系统挂了一次,他们在那边搞不定,希望我能出差支持一下,我说好的那我明天去,领导说能否今天晚上就去,没办法,订了10点多的机票,匆匆忙忙的赶到机场,由于飞机晚点,到厦门已经是凌晨2点了.到了以后,我还没找到地方住下,厦门这边的PM就给我打电话,直接去他们的办公场所解决问题,于是直接去了厦门软件园,到了以后,当时心里是很感动的,因为还有一波人在那里等着我一起和他们解决问题,想想大家都挺不容易的. 1.五个

编程语言中,何谓“一等公民”

http://blog.csdn.net/hikaliv/article/details/4588163 一等公民,First-Class Citizen,此处 Citizen 可换为 object / value / entity 等词.所谓"一等公民"即指在程序中可无限使用的对像(相比其它对像)."一等公民"者可以: 表示为匿名字面值 存储于变量中 存储于数据结构中 作为函数的参数传递 作为函数的返回值 在运行时构造

Java 语言中 Enum 类型的使用介绍

Enum 类型的介绍 枚举类型(Enumerated Type) 很早就出现在编程语言中,它被用来将一组类似的值包含到一种类型当中.而这种枚举类型的名称则会被定义成独一无二的类型描述符,在这一点上和常量的定义相似.不过相比较常量类型,枚举类型可以为申明的变量提供更大的取值范围. 举个例子来说明一下,如果希望为彩虹描绘出七种颜色,你可以在 Java 程序中通过常量定义方式来实现. 清单 1. 常量定义 Public static class RainbowColor { // 红橙黄绿青蓝紫七种颜

php语言中Excel表格导入数据库的方法详解

在php编程语言中,对于如何在Excel表格中导入数据库的方法是很多编程者比较头疼的一个问题,有些技术人员可能在百度尝试过搜索很多不同的问题,但是给出的答案经过自己测试之后,发现还是行不通,那么对此,燚轩科技也尝试了一下如何在Excel表格中导入数据库,现在将源代码展示给各位技术编程者,大家可以借鉴参考一下. public function saveexcel(){require_once('./Thinkphp/Extend/Vendor/PHPExcel-1.8/Classes/PHPExc

深入理解JavaScript系列:为什么03-0.2不等于0.1

五一宅家看书,所以接着更新一篇文章. 今天讲一下为什么03-0.2不等于0.1这个问题. 有点标题党的味道,在JavaScript中,当你试着对小数进行加减运算时,有时候会发现某个结果并非我们所想的那样,就比如标题中所说的为什么我用0.3去减0.2却得不到0.1? 当我碰到这个问题的时候我一下子也不知道问题到底出在哪,但他实实在在的就给出了一个0.09999999999999998的结论. 其实这个问题的本质原因就是在于计算机对浮点数的处理上,对于计算机的运算方法和数据的表示处理等内容是很大的一

C/C++语言中NULL、'\0’和0的区别

注:本文参考了http://blog.csdn.net/mylinx/article/details/6873253及书籍<征服C指针>([日]前桥和弥著). NULL.'\0'和0的值是一样的,都是0,不过它们的表现形式不一样: 1. NULL: 即空指针,不过在C和C++中并不一样.在VS 2013的库文件string.h中可以看到如果定义. 1 /* Define NULL pointer value */ 2 #ifndef NULL 3 #ifdef __cplusplus 4 #d

C语言中do...while(0)的妙用(转载)

转载来自:C语言中do...while(0)的妙用,感谢分享. 在linux内核代码中,经常看到do...while(0)的宏,do...while(0)有很多作用,下面举出几个: 1.避免goto语句: 通常,如果一个函数开始要分配一些资源,然后如果在中途遇到错误则要退出函数,当然,退出前要释放资源,我们的代码可能如下: 1 #defien N 10 2 3 bool Execute() 4 { 5 // 分配资源 6 int *p = (int *)malloc(N * sizeof(int

R语言中的logical(0)和numeric(0)以及赋值问题

logical(0) 不等于 numeric(0).两者都不等于NULL值,即is.null(logical(0))和is.null(numeric(0))返还值都是FALSE.这很有意思,说明长度为零的值有时却不会别算为空值,但空值的定义却是函数中没有被赋值的参数,特征就是没有值.如何区分NULL和NA?很简单,后者的logical length是1,而前者的logical length是0,意思是假如用is.logical判断NA的逻辑值,得到的结果是TRUE.NA可以为正无穷或负无穷,但N

C语言中setjmp与longjmp学习笔记

一.基础介绍 ?? ?头文件:#include<setjmp.h> ?? ?原型:??int?setjmp(jmp_buf envbuf) ?? ?宏函数setjmp()在缓冲区envbuf中保存系统堆栈里的内容,供longjmp()以后使用.首次调用setjmp()宏时,返回值为0,然而longjmp()把一个变原传递给setjmp(),该值(恒不为0)就是调用longjmp()后出现的setjmp()的值. void longjmp(jmp_buf envbuf,int status);