”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 超越 JavaScript - 为什么 + 在编程中不等于

超越 JavaScript - 为什么 + 在编程中不等于

发布于2024-11-01
浏览:291

当开发者第一次遇到这个看似令人费解的结果时,JavaScript 经常被嘲笑:

0.1   0.2 == 0.30000000000000004

关于 JavaScript 处理数字的模因很普遍,常常导致许多人相信这种行为是该语言所独有的。

Beyond JavaScript - Why     doesn

然而,这个怪癖不仅仅局限于 JavaScript。这是大多数编程语言处理浮点运算方式的结果。

例如,以下是来自 JavaGo 的代码片段,它们产生类似的结果:

Beyond JavaScript - Why     doesn

Beyond JavaScript - Why     doesn

计算机本身只能存储整数。他们不懂分数。 (他们会怎么做?计算机进行算术运算的唯一方法是打开或关闭一些灯。灯可以打开或关闭。它不能“半”亮!)他们需要某种表示浮点数的方法。由于这种表示方法并不完全准确,因此 0.1 0.2 通常不等于 0.3。

所有分母由数系基数的质因数组成的分数都可以清晰地表达,而任何其他分数都会有重复的小数。例如,在以 10 为基数的数字系统中,可以清楚地表示 1/2、1/4、1/5、1/10 等分数,因为每种情况下的分母均由 2 或 5(10 的质因数)组成然而,像 1/3、1/6、1/7 这样的分数都有循环小数。

同样,在二进制系统中,像 1/2、1/4、1/8 这样的分数都可以清晰地表达,而所有其他分数都有循环小数。当您对这些循环小数执行算术运算时,您最终会得到剩余的内容,当您将计算机的数字二进制表示形式转换为人类可读的以 10 为基数的表示形式时,这些剩余内容会继续存在。这就是导致大致正确结果的原因。

既然我们已经确定这个问题并非 JavaScript 所独有,那么让我们探讨一下浮点数是如何在幕后表示和处理的,以了解为什么会出现这种行为。

为了了解浮点数在底层是如何表示和处理的,我们首先必须了解IEEE 754浮点标准。

IEEE 754 标准是一种广泛使用的规范,用于在计算机系统中表示浮点数并对其执行算术运算。它的创建是为了保证在各种计算平台上使用浮点运算时的一致性。大多数编程语言和硬件实现(CPU、GPU 等)都遵守此标准。

这是数字在 IEEE 754 格式中的表示方式:

Beyond JavaScript - Why     doesn

这里s是符号位(0表示正数,1表示负数),M是尾数(保存数字的位数)和E 是决定数字小数位数的指数。

您将无法找到任何可以在此格式中精确表示数字(如 0.1、0.2 或 0.3)的 M 和 E 整数值。我们只能选择给出最接近结果的 M 和 E 值。

这里有一个工具,您可以用来确定 IEEE 754 十进制数表示法:https://www.h-schmidt.net/FloatConverter/IEEE754.html

IEEE 754 0.25 表示法:

Beyond JavaScript - Why     doesn

IEEE 754 分别表示 0.1 和 0.2:

Beyond JavaScript - Why     doesn
Beyond JavaScript - Why     doesn

请注意,0.25时转换误差为0,而0.1和0.2则为非零误差。

IEEE 754 定义了以下表示浮点数的格式:

  • 单精度(32 位):1 位符号,8 位指数,23 位尾数

  • 双精度(64 位):1 位符号,11 位指数,52 位尾数

为了简单起见,让我们考虑使用 32 位的单精度格式。

0.1的32位表示为:

0 01111011 10011001100110011001101

这里第一位代表符号(0在本例中表示正数),接下来的8位(01111011)代表指数,最后23位(10011001100110011001101)代表尾数。

这不是准确的表示。它代表 ≈ 0.100000001490116119384765625

同样,0.2的32位表示为:

0 01111100 10011001100110011001101

这也不是准确的表示。它代表 ≈ 0.20000000298023223876953125

添加后,结果是:

0 01111101 11001101010011001100110 

十进制表示中的 ≈ 0.30000001192092896

总之,看似令人困惑的结果 0.1 0.2 不产生 0.3 并不是 JavaScript 特有的异常现象,而是跨编程语言的浮点运算限制的结果。这种行为的根源在于数字的二进制表示形式,这在处理某些分数时本质上会导致精度错误。

版本声明 本文转载于:https://dev.to/umangsinha12/beyond-javascript-why-01-02-doesnt-equal-03-in-programming-2bf3?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何从Google API中检索最新的jQuery库?
    如何从Google API中检索最新的jQuery库?
    从Google APIS 问题中提供的jQuery URL是版本1.2.6。对于检索最新版本,以前有一种使用特定版本编号的替代方法,它是使用以下语法:获取最新版本:未压缩)While these legacy URLs still remain in use, it is recommended ...
    编程 发布于2025-03-09
  • 如何在Java字符串中有效替换多个子字符串?
    如何在Java字符串中有效替换多个子字符串?
    在java 中有效地替换多个substring,需要在需要替换一个字符串中的多个substring的情况下,很容易求助于重复应用字符串的刺激力量。 However, this can be inefficient for large strings or when working with nu...
    编程 发布于2025-03-09
  • 如何使用PHP从XML文件中有效地检索属性值?
    如何使用PHP从XML文件中有效地检索属性值?
    从php PHP陷入困境。使用simplexmlelement :: attributes()函数提供了简单的解决方案。此函数可访问对XML元素作为关联数组的属性: - > attributes()为$ attributeName => $ attributeValue){ echo ...
    编程 发布于2025-03-09
  • 如何干净地删除匿名JavaScript事件处理程序?
    如何干净地删除匿名JavaScript事件处理程序?
    删除匿名事件侦听器将匿名事件侦听器添加到元素中会提供灵活性和简单性,但是当要删除它们时,可以构成挑战,而无需替换元素本身就可以替换一个问题。 element? element.addeventlistener(event,function(){/在这里工作/},false); 要解决此问题,请考虑...
    编程 发布于2025-03-09
  • 如何使用Regex在PHP中有效地提取括号内的文本
    如何使用Regex在PHP中有效地提取括号内的文本
    php:在括号内提取文本在处理括号内的文本时,找到最有效的解决方案是必不可少的。一种方法是利用PHP的字符串操作函数,如下所示: 作为替代 $ text ='忽略除此之外的一切(text)'; preg_match('#((。 &&& [Regex使用模式来搜索特...
    编程 发布于2025-03-09
  • 大批
    大批
    [2 数组是对象,因此它们在JS中也具有方法。 切片(开始):在新数组中提取部分数组,而无需突变原始数组。 令ARR = ['a','b','c','d','e']; // USECASE:提取直到索引作...
    编程 发布于2025-03-09
  • 可以在纯CS中将多个粘性元素彼此堆叠在一起吗?
    可以在纯CS中将多个粘性元素彼此堆叠在一起吗?
    [2这里: https://webthemez.com/demo/sticky-multi-header-scroll/index.html </main> <section> { display:grid; grid-template-...
    编程 发布于2025-03-09
  • 为什么使用Firefox后退按钮时JavaScript执行停止?
    为什么使用Firefox后退按钮时JavaScript执行停止?
    导航历史记录问题:JavaScript使用Firefox Back Back 此行为是由浏览器缓存JavaScript资源引起的。要解决此问题并确保在后续页面访问中执行脚本,Firefox用户应设置一个空功能。 警报'); }; alert('inline Alert')...
    编程 发布于2025-03-09
  • Java是否允许多种返回类型:仔细研究通用方法?
    Java是否允许多种返回类型:仔细研究通用方法?
    在Java中的多个返回类型:一种误解类型:在Java编程中揭示,在Java编程中,Peculiar方法签名可能会出现,可能会出现,使开发人员陷入困境,使开发人员陷入困境。 getResult(string s); ,其中foo是自定义类。该方法声明似乎拥有两种返回类型:列表和E。但这确实是如此吗...
    编程 发布于2025-03-09
  • HTML格式标签
    HTML格式标签
    HTML 格式化元素 **HTML Formatting is a process of formatting text for better look and feel. HTML provides us ability to format text without us...
    编程 发布于2025-03-09
  • 我可以将加密从McRypt迁移到OpenSSL,并使用OpenSSL迁移MCRYPT加密数据?
    我可以将加密从McRypt迁移到OpenSSL,并使用OpenSSL迁移MCRYPT加密数据?
    将我的加密库从mcrypt升级到openssl 问题:是否可以将我的加密库从McRypt升级到OpenSSL?如果是这样,如何?答案:是的,可以将您的Encryption库从McRypt升级到OpenSSL。可以使用openssl。附加说明: [openssl_decrypt()函数要求iv参...
    编程 发布于2025-03-09
  • 如何从PHP中的数组中提取随机元素?
    如何从PHP中的数组中提取随机元素?
    从阵列中的随机选择,可以轻松从数组中获取随机项目。考虑以下数组:; 从此数组中检索一个随机项目,利用array_rand( array_rand()函数从数组返回一个随机键。通过将$项目数组索引使用此键,我们可以从数组中访问一个随机元素。这种方法为选择随机项目提供了一种直接且可靠的方法。
    编程 发布于2025-03-09
  • 如何使用不同数量列的联合数据库表?
    如何使用不同数量列的联合数据库表?
    合并列数不同的表 当尝试合并列数不同的数据库表时,可能会遇到挑战。一种直接的方法是在列数较少的表中,为缺失的列追加空值。 例如,考虑两个表,表 A 和表 B,其中表 A 的列数多于表 B。为了合并这些表,同时处理表 B 中缺失的列,请按照以下步骤操作: 确定表 B 中缺失的列,并将它们添加到表的末...
    编程 发布于2025-03-09
  • 为什么Microsoft Visual C ++无法正确实现两台模板的实例?
    为什么Microsoft Visual C ++无法正确实现两台模板的实例?
    The Mystery of "Broken" Two-Phase Template Instantiation in Microsoft Visual C Problem Statement:Users commonly express concerns that Micro...
    编程 发布于2025-03-09

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3