字节面试 用double,1.0-0.9的结果不是0.1,为什么?

news/2024/10/6 3:43:55/文章来源:https://www.cnblogs.com/codewd/p/18285941

让我详细解释一下为什么 1.0 - 0.9 在二进制中不能精确表示。

1.0 的二进制表示

1.0 在二进制中可以精确表示。它的二进制表示为:

1.0 = 1.0 (二进制)

0.9 的二进制表示

0.9 是一个无法在二进制中精确表示的小数。二进制小数是通过求和 1/2, 1/4, 1/8, 1/16, ... 等幂次表示的。对于 0.9,二进制表示需要不断近似:

0.9 ≈ 0.1110011001100110011001100110011... (二进制)

这是一个无限循环小数。

计算误差

由于计算机中浮点数的存储位数是有限的,无法存储无限位数的小数。因此,计算机会将 0.9 近似为一个有限位数的二进制小数,这就引入了误差。例如,在 IEEE 754 双精度浮点数标准下,0.9 的表示近似为:

0.9 ≈ 0.89999999999999991118... (二进制)

结果的影响

当我们计算 1.0 - 0.9 时,实际上是在用近似值进行计算:

1.0 - 0.89999999999999991118 ≈ 0.10000000000000008882

这就是为什么你会发现计算结果不是精确的 0.1,而是一个非常接近但不完全相同的值。

总结来说,浮点数的二进制表示导致了 0.9 不能被精确表示,从而在计算中引入了误差。希望这个解释清楚了为什么会有这种情况。

详细说明double=0.9的表示方式

在计算机中,double 类型用于表示双精度浮点数,遵循 IEEE 754 标准。这个标准规定了浮点数的存储和表示方法。一个 double 类型的数在内存中占用 64 位,其中包含 1 位符号位,11 位指数位,以及 52 位尾数位。

将 0.9 表示为 double

  1. 十进制到二进制:

    如前所述,0.9 在二进制中是一个无限循环小数:
    [ 0.9_{10} = 0.1110011001100110011..._2 ]

  2. 规范化浮点表示:

    将二进制小数规范化为 (1.x) 形式,同时调整指数。例如:
    [ 0.1110011001100110011..._2 = 1.1100110011001100110011..._2 \times 2^{-1} ]

  3. 提取尾数和指数:

    尾数(Mantissa)部分为:1100110011001100110011001100110011001100110011001101
    指数部分为:-1

  4. 偏移指数:

    IEEE 754 标准中,双精度浮点数使用偏移量为 1023 的偏移指数。因此:
    [ -1 + 1023 = 1022 ]
    将 1022 转换为二进制:
    [ 1022_{10} = 1111111110_2 ]

  5. 组合位串:

    现在,我们可以将符号位、偏移后的指数位和尾数组合起来。

    • 符号位(0 表示正数):0
    • 指数位:1111111110
    • 尾数位:1100110011001100110011001100110011001100110011001101

    因此,0.9 在 double 类型中的二进制表示为:
    [ 0 , 1111111110 , 1100110011001100110011001100110011001100110011001101 ]

总结

在计算机内部,0.9 被表示为 IEEE 754 双精度浮点数,其二进制表示在内存中具体如下:

  • 符号位:0
  • 指数位:1111111110(十进制的 1022)
  • 尾数位:1100110011001100110011001100110011001100110011001101

当你在代码中赋值 double x = 0.9; 时,编译器会将 0.9 转换为上述的二进制表示,存储在内存中。这种表示方式因为精度限制,实际上存储的数值并不是精确的 0.9,而是一个非常接近 0.9 的数值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/738793.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于oracle中的undo

一,undo介绍 二,undo视图说明 三,常用脚本说明 四.释放UNDO表空间 五.参考 一,undo介绍 Oracle中 undo的作用主要有两个:第一是回滚事务,第二是产生一致性读。同时也衍生出了一些新的 功能,比如Flashback query。传统的 undo是通过undo segment 来管理的,我们看下面的示…

闪迪U盘数据恢复

一、检查并取消隐藏项目 连接U盘:首先,确保闪迪U盘与电脑稳定连接。 打开U盘目录:在电脑中找到并打开U盘所在的目录。 显示隐藏项目:在文件资源管理器的顶部菜单中,点击“查看”选项,并勾选“显示隐藏的项目”。如果数据只是被隐藏了,这一步应该能够显示出被隐藏的文件。…

移动硬盘坏道修复

一、使用系统自带的磁盘检查工具 如果使用的是Windows系统,可以通过系统自带的磁盘检查工具来尝试修复坏道。 连接移动硬盘:首先,确保移动硬盘已经通过USB线连接到电脑上,并且系统能够识别到它。 打开磁盘属性:在文件资源管理器中,右键点击移动硬盘的图标,选择“属性”。…

MyBatis-Plus-实用的功能自动填充字段

MyBatis-Plus-实用的功能自动填充字段前言: java项目用到了mybatis-plus,在一些类里面需要在更新时候,统一设置,修改人,修改ID,修改时间。新增时候设置 创建人,创建时间等 基础类:@Data public abstract class BaseModel implements Serializable {/*** 逻辑删除*/@Tabl…

BOSHIDA DC/AC电源模块在不同的电源类型之间进行转换

BOSHIDA DC/AC电源模块在不同的电源类型之间进行转换 电力转换是现代社会不可或缺的一部分,它使我们能够在不同的电源类型之间进行转换,从而满足各种设备和应用的需求。DC/AC电源模块是一种用于将直流电转换为交流电的设备,它在电子设备、太阳能系统、电池充电等领域发挥着重…

面试必会之SpringBootSpringCloud

01- 讲一讲SpringBoot自动装配的原理 1.在SpringBoot项目的启动引导类上都有一个注解@SpringBootApplication @SpringBootApplication @MapperScan("com.hxx.admin.dao") public class AdminApplication {public static void main(String[] args) {SpringApplication…

在Docker中搭建rabbit MQ集群 (Mac + OrbStack)

我以为用docker搭建一个rabbitMq集群会非常简单,但是结果却出乎意料,我花了差不多两个半天才搞定。这还是依赖了AI的协助,否则难度不敢想象。我的环境是Mac上的OrbStack。用了Kimi + 文心一言 + ChatGPT + Claude,还是Kimi价值最大。back and forth 的过程就不讲了,这里直…

信息安全驱动汽车行业快速向数字化转型

经纬恒润针对ISO/SAE 21434、WP.29 R155等法规进行了深入研究,结合多年功能安全、信息安全经验,可以为客户提供信息安全全流程解决方案。 开发一款安全性良好的软件是困难的,它需要专业知识的积累以及对常见编程缺陷和规则的了解,例如检查输入范围、管理内存分配和回…

Java进阶:HashMap底层原理(通俗易懂篇)

1.底层结构 Java 7及之前版本 在Java 7及之前的版本中,HashMap的底层数据结构主要是数组加链表。具体实现如下:数组:HashMap的核心是一个Entry数组(Entry<K,V>[] table),这个数组的大小总是2的幂。每个数组元素是一个单一的Entry节点,或者是一个链表的头节点。链表…

各类问题p~np

可以简单用下图来表示 p类问题指的是可以在多项式时间求解的问题,例如n个数的排序问题,复杂度最多为O^2 np类问题指的是可以在多项式时间验证答案的问题,例如求n个点的图是否有哈密顿路,最坏情况需要(n-1)!,但是验证是否为哈密顿路是多项式时间 nph类问题是任意np类问题在…

面试必会之Redis篇

01- 你们项目中哪里用到了Redis ? 在我们的项目中很多地方都用到了Redis , Redis在我们的项目中主要有三个作用 :使用Redis做热点数据缓存/接口数据缓存 使用Redis存储一些业务数据 , 例如 : 验证码 , 用户信息 , 用户行为数据 , 数据计算结果 , 排行榜数据等 使用Redis实现分…