If you're seeing this message, it means we're having trouble loading external resources on our website.

如果你被网页过滤器挡住,请确保域名*.kastatic.org*.kasandbox.org 没有被阻止.

主要内容

数量限制,溢出和舍入

当计算机程序用变量存储数字时,计算机需要有办法在内存中表达该数字。 计算机会根据一个数字是否为整数而使用不同的策略。由于计算机内存的限制,程序有时会遇到数字变量舍入溢出,或精度问题。

整数表示法

整数 是指任何可以不需分数部分即可表达的数字。 同样的定义在编程和数学都适用,希望您对此已熟悉。
所有这些数字都是整数:12010020
编程语言怎样在内存中表示那些整数呢?其实,计算机用二进制表示 所有数据 , 所以我们知道,最终以上的每一个数都是一系列的0和1。
我们从简单情况开始,假设一台计算机只能使用 4 位来表示整数。它可以使用第一位来表示整数的符号,是正还是负,然后用其他 3 位表示绝对值。
在这个系统中,数字 1 表示为:
0001
+/-421
符号222120
符号位的 0 表示这是个正数,最右位的 1 表示 20 (1) 位置的值。
这个系统可以表示的最大数字是什么?我们把所有数值位都填上 1 看看:
0111
+/-421
符号222120
这是正整数 7,因为 22+21+20=(4+2+1)=7.
测验你的理解
考虑一个使用 6 位表示整数的计算机:1 位表示符号,5 位表示数值。它可以表示的最大正整数是多少?
  • 你的答案是
  • 一个整数,例如 6
  • 一个最简真分数,如 3/5
  • 一个最简假分数,如 7/4
  • 一个混合带分数,例如 1 3/4
  • 一个精确的十进位小数,例如0.75
  • pi 的倍数, 例如 12\ \text{pi} 或 2/3\ \text{pi}$

溢出

当我们在一台最大正整数为 7 的 4 位计算机上,运行下面程序会发生什么呢?
var x = 7;
var y = x + 1;
这台计算机可以正常储存变量 x 的值,但变量 y 的值比 4 位计算机所能表示的最大正整数还要大 1。这种情况下,计算机可能会报告“溢出错误”,或者显示类似“数值太大”的信息。它还可能会截断数据(所有结果限制为 7),或者回绕数据(结果 8 变成 1)。
上述任何情况我们都不想发生,所以在编写程序时,我们要清楚的了解所使用的语言和环境的限制,这个很重要。
测验你的理解
在一个 6 位计算机上(1 位表示符号),下列哪个操作会导致溢出?
选择所有正确的答案:

幸运的是,大多数现代计算机都是用 64 位架构,可以储存不可思议的大整数。在 JavaScript 中,最大的安全整数是 9,007,199,254,740,992,等于 2521。如果超过这个数,就是危险区域了。
✏️ 在危险区域试探试探吧!JavaScript 不会显示溢出错误,但会做一些其他的奇怪动作。
📝 查看不同语言下的类似程序: App Lab | Snap | Python

浮点表示法

我们已经知道计算机储存整数是有限制的。而那些非整数,比如分数和无理数,在计算机内存中更难以表示。
考虑这样的数:2/51.2349.999999,以及著名的无理数 π
计算机语言通常使用浮点表示法来表示非整数(有时也表示整数)。这种表示法很像你在别的课上学过的“科学记数法”。
浮点表示法的格式为,一个数乘以一个底数的指数次方。
300=3×10底数2对应的指数
由于计算机使用的是二进制系统,而不是十进制系统,所以浮点数的底数为 2 而不是 10。正因为如此,2 的整数次幂是最容易表示的:
128=1×27256=1×28
而在 2 的整数次幂之间的数可以表示为:
160=1.25×27192=1.50×27224=1.75×27
那么非整数呢?同样,2 的整数次幂(这里是负整数)最容易表示:
0.50=1×210.25=1×22
浮点法同样可以表示 2 的整数次幂之间的数:
0.750=1.5×210.375=1.5×22
计算机确定了一个数的浮点表示法之后,就可以将其储存在 0-1 数位中了。现代计算机使用 64 位系统,其中符号占 1 位,11 位储存指数,剩下 52 位储存前面的数。
下面是 0.375 的二进制浮点表示:
11,111,111,011,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000
各数位确切的意义要更复杂一些,我们这里不展开讲,但如果你有兴趣,这会是个非常棒的题目,完全可以自己去研究了解。

舍入误差

然而浮点表示法仍然无法完整表示部分数字。考虑分数 1/3,它的浮点表示为:
1/3=1.3×22
就算在二进制中,.3 也仍然是一个无限循环的序列:
101,010,101…
我们不能在计算机中储存无限序列!计算机必须在某个时刻,以某种方式停止这个无限序列,要么直接截断,要么四舍五入到最接近的浮点数。计算机会非常频繁的这样做,因为就算是像 1/10(在十进制中表示为短短的 0.1)这样的分数,在转换为二进制时也会变成无限循环序列。
通常我们并不关心一个数的低位精确度,但计算时就得关心了。因为计算结果可能会有 舍入误差
✏️ 下面是一个试图计算 0.1+0.1+0.1 的程序。在现实世界中,我们知道答案是 0.3。但是在计算机的世界中,每一个 0.1 都储存为一个四舍五入过的二进制小数,当它们加起来的时候,答案可能跟我们想的不一样……
📝 查看不同语言下的类似程序: App Lab | Snap | Python
我们使用的数位越多,我们储存和计算的精度就会越高。现代的 64 位系统给我们提供了足够高的精度,足够处理一般计算。
也许以后你会有机会编写程序来计算投票结果、驱动自动驾驶汽车,或者发射火箭的时候。在利害攸关的重大场合,精确度特别重要。

🙋🏽🙋🏻‍♀️🙋🏿‍♂️你对这个章节还有问题吗? 我们会尽力回答— 请在下面提问框里留言!

想加入讨论吗?

尚无帖子。
你会英语吗?单击此处查看更多可汗学院英文版的讨论.