跟我到CPU内部去看1+1=2是如何运行的!(2)

本文通过深入浅出的方式介绍了1+1=2这一简单数学运算在CPU内部的具体实现过程。从晶体管的基本作用出发,解释了二进制数在计算机中的表示方式,并进一步说明了加法运算通过逻辑门和加法器完成的工作原理。

         在上文中你知道1+1=2是如何在cpu中运作的么?----跟我到cpu内部去看看吧!(1) 我们通过旅游的视角已经的揭开了CPU的一角面纱,到现在为止我们可以清楚一下两件事情.


         1  晶体管是CPU中的核心部件.

         2 可以通过控制晶体管并对其进行逻辑组合便可以计算.


         那么1+1=2是如何通过晶体管来进行呢?

        要知道1+1=2如何运作,首先需要知道12 在计算机中如何通过晶体管来表示呢?


         在上文中我们已经提到,一个小灯泡的状态可以通过两个晶体管(开关)进行逻辑组合来控制.现在你可以这样理解:


        一个小灯泡的状态代表着计算机中的两个数值:亮着表示1 关闭表示0

        现在我们可以拿出四个小灯泡,并且把四个小灯泡排成一排,如果你稍微懂一些二进制的话,现在已经很清楚了.我们可以通过这四个小灯泡的开关组合最多能够表示我们常用数制即十进制的16个数字(也就是24次方).


       现在就会有一下情况出现:

1 四个小灯泡全部熄灭:                           二进制:0000   十进制:0

2 从右面数第一个小灯泡打开,其他关闭:   二进制:0001      十进制:1 

3 从右面数第二个小灯泡打开,其他关闭二进制:0010   十进制:2

依次类推,直到全部的四个小灯泡都打开:   二进制:1111   十进制15

 

以上过程可以通过下图来进行概括:

 

 

计算机生成了可选文字: 月.098761匀43丹乙月.0月.月.00000nU0000―丁十丰―丁十十工―丁十牛上土!1、0、1、1(,1:01:O:,,:00,:i,010:O宕10111;1:1011110;101101,};011010}00'1'1:00,O0001:'00'00';留谷曾曾

 

 

      那么1+1=2如果用上图进行表示的话可以得到下面的示例图:

 

 

计算机生成了可选文字: 月.月.J『.月.曰.〕户.妇0000月.月.月.月.J『.J飞.翻.』翻r』月.月.月.月.月.月.月.月.曰.』翻.〕月.月.月.月.0:0:11丁才不而0;0!0:10000QQ日Q月.月.月.月.00011O云000云QQQQ④日Q公

 

       好了,至此为止我们已经知道1 2 还有其他的数值是如何在计算机中通过晶体管来表示,但具体"+"的这个过程是如何运行呢?

 

     现在我们开始进行下一步的理解.

     把一个晶体管抽象成一个开关,一个开关可以表示数字10,我们可以通过连接两个开关和两个灯泡通过一定的结构,开关用来表示输入0或者1 而两个灯泡表示通过特殊结构的处理所得到的结果,这个特殊结构便是"加法器".加法器里面都是有各种逻辑门来构成的.这些逻辑门包括:"","",""与非" ,两个开关通过加法器相连的逻辑图如下

 

 

 

     

计算机生成了可选文字: H日IfAddef翩O.栩一.』一.一.』口且.}一.}.一日.}一月.一


         上图只是一个两个开关的相加,但是计算机要处理的是庞大的数据,这就需要将一个个的开关进行逻辑的相连接,变形成了下面的图,通过下图的方式将一个个的开关和灯泡进行相连.

 

计算机生成了可选文字: HalfAdderl泛\{朋一/一AND.,日OR长H日!fAdd6r卜‘八咤角八囚O目价目口.,日ANO〔用

 

如果有两排八个开关通过加法器相连,没有一个开关的话.从宏观的角度来看的话,便是下图所示:

       

计算机生成了可选文字: 回回圈0。回回日。。回回圈0。回回圈0。回尚图日向U回回囚品》回回圈印。回回圃问。0『0009000二0009000

 

      而我们此次的主角:1+1=2的运作流程便是下图所示

 

计算机生成了可选文字: .曰日.10000000,回回回回回回回1D0000O01回回回回回回回}回+圈日日圈圈日瞥曾曾曾曾曾几BOO,决dd陌四.,01CO吕.栩八BC.,,0决山如dA卜10CO,u旧2200000010曾

 

        此篇博客解决在准备软件设计师的过程中的疑惑.通过对CPU运作原理的探索,再一次理解了大道至简的道理,我们看似复杂的CPU,看似复杂的很多事物,归根到底都是一些特别简单的元素,而也就是这些"元素"通过各种组合,变换,便形成了复杂的运算,解决各种复杂的问题.

      

       想起了老子<<道德经>>里的一段话:“道生一,一生二,二生三,三生万物,万物负阴而抱阳,冲气以为和。”


         

<think>我们正在讨论的是Java中的浮点数精度问题。用户提到在Java代码中计算(1 + 0.01)得到1.01,但实际在计算机内部可能是近似值。用户引用的资料表明,浮点数在计算机中无法精确表示,因此可能会产生舍入误差。 问题:为什么在Java中(1 + 0.01)的结果显示为1.01? 原因分析: 在Java中,浮点数(如float和double)采用IEEE 754标准表示。这种表示法在二进制中可能无法精确表示某些十进制小数(例如0.01)。因此,0.01在计算机内部实际上是一个近似值。 但是,当我们执行1 + 0.01时,为什么打印出来是1.01呢? 这是因为Java在打印浮点数时,默认会进行舍入,只显示一定数量的有效数字(对于double,通常显示15-16位十进制数字)。因此,即使内部表示是近似值,打印时也可能显示为我们期望的“1.01”。 然而,如果我们要求更高的精度(例如打印更多小数位),就会看到实际值并不是精确的1.01。 我们可以通过一个简单的程序来验证: ```java public class FloatingPointTest { public static void main(String[] args) { double a = 1.0; double b = 0.01; double sum = a + b; System.out.println(sum); // 输出 1.01 // 以更高的精度打印 System.out.printf("%.20f%n", sum); // 输出 1.01000000000000000000? 实际上可能不是精确的 } } ``` 实际上,0.01的二进制表示是一个无限循环小数,类似于十进制中的1/3(0.333...)。因此,在计算机中存储0.01时,它被近似为一个最接近的可表示的浮点数。当我们加上1.0(可以精确表示)时,结果也是近似的。但是,由于打印时默认四舍五入到小数点后两位,我们看到的是1.01。 更精确地说,0.01在double精度下的实际值大约是0.01000000000000000020816681711721685132943093776702880859375(你可以通过以下代码查看0.01的精确值): ```java System.out.println(new BigDecimal(0.01)); ``` 因此,1 + 0.01的实际内部值大约是1.01000000000000000020816681711721685132943093776702880859375,但当我们使用`System.out.println`打印时,它会被舍入为1.01。 结论:浮点数的显示和实际存储值可能不同,显示时进行了舍入,因此我们看到的是1.01。 引用[1]和[2]说明了浮点数在计算机中的表示问题,以及为什么会出现精度误差。在金融计算等需要精确计算的场合,建议使用`BigDecimal`类。 根据用户提供的引用,我们还可以看到,当进行多次浮点数运算时,误差可能会累积,导致结果与预期不符(如引用[1]中提到的0.01变成了0.009999999999999787)。 因此,在需要精确计算的场合(如货币计算),应避免使用double或float,而应使用BigDecimal。 相关问题: 1. 在Java中如何精确表示和计算货币? 2. 为什么0.01在计算机中无法精确表示? 3. 如何避免浮点数运算中的精度损失? 现在,我们根据上述分析编写回答。</think>### Java 中 `(1 + 0.01)` 为何显示为 1.01 的解释 在 Java 中,当您执行 `(1 + 0.01)` 时,虽然计算结果在二进制浮点数中并非精确等于数学上的 1.01,但输出时仍显示为 "1.01"。这是由以下机制共同作用的结果: #### 1. **浮点数的二进制表示限制** - Java 的 `double` 类型使用 IEEE 754 标准存储浮点数 - 十进制小数 0.01 在二进制中是无限循环小数: $$0.01_{10} = 0.000000101000111101011100001010001111010111..._2$$ - 实际存储值约为: $$0.01_{double} \approx 0.010000000000000000208166817117216851..._{10}$$ #### 2. **加法运算的舍入机制** ```java double result = 1.0 + 0.01; // 实际存储值 ≈ 1.010000000000000000208... ``` - CPU 执行浮点加法时: 1. 将 1.0(精确表示为 $2^0$)转换为浮点格式 2. 将 0.01 转换为最接近的可表示浮点值 3. 执行二进制加法 4. 结果再次舍入到最接近的可表示浮点值 #### 3. **输出时的格式化处理** - `System.out.println()` 默认只显示有效数字: ```java System.out.println(1.0 + 0.01); // 输出 "1.01" ``` - 实际值可通过高精度打印验证: ```java System.out.printf("%.20f", 1.0 + 0.01); // 输出:1.01000000000000000021 ``` #### 4. **精度损失的根本原因** | 数据类型 | 精度位 | 十进制精度 | 示例误差 | |----------|--------|------------|----------| | `float` | 23位 | 6-7位小数 | `0.01f + 0.01f ≠ 0.02f` | | `double` | 52位 | 15-16位小数 | `0.01 + 0.01 == 0.02` ✅ | 在您的案例中: $$(1 + 0.01)_{double} = 1.010000000000000000208... \approx 1.01_{display}$$ 显示时被舍入为 1.01[^2] ### 金融计算的正确实践 为避免精度问题,推荐使用 `BigDecimal`: ```java import java.math.BigDecimal; public class PrecisionDemo { public static void main(String[] args) { BigDecimal one = new BigDecimal("1.0"); BigDecimal rate = new BigDecimal("0.01"); BigDecimal result = one.add(rate); System.out.println(result); // 精确输出 1.01 } } ``` `BigDecimal` 通过字符串初始化避免二进制舍入误差[^1] ### 关键结论 1. **显示精度 ≠ 存储精度**:输出时自动舍入到可读格式 2. **浮点数本质**:所有浮点运算都有微小误差,但 Java 的输出优化使其对人类"透明" 3. **金融场景**:必须使用 `BigDecimal` 避免累积误差
评论 87
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值