计算机中如何表示分数?

9
由于计算机是以“1”和“0”为基础进行运算的,那么它们如何计算和表示诸如7.50这样的分数?我知道Java和JavaScript,如果需要,您可以使用它们作为示例。
编辑:我正在观看 MIT教授Cormen关于哈希的视频,在46:31秒处,他使用一个模块化轮来解释乘法哈希函数,该轮是一个单位圆,其中有几个点表示分数。这促使我在此向SO提出这个基本问题。

Here - big zero
3个回答

12
计算机上表示非整数的最常见方式是使用浮点数,特别是IEEE 754浮点数。通常情况下,我们使用硬件位来表示二进制数字表示整数,所以物理性质(如电荷或不带电荷、高电压或低电压、一个方向或另一个方向的磁场)用于表示位(0和1),一系列这些位组成一个数字(如11010),我们将其解释为二进制表示的一个数字(110102是16+8+2=26)。我们通常不会想到,但是这个数字右边有一个“小数点”,在我们需要表示分数时才需要使用它。例如,11010.112是16+8+2+1/2+1/4=26.75。要从整数转换为浮点数,我们使小数点浮动。除了表示数字的位之外,我们还有一些额外的位告诉我们该放置小数点的位置。
因此,我们可能有三个位,例如010,用于指示小数点的位置,其他位,例如1101011,用于表示值。小数点位010可能表示将小数点向左移两个位置,将“1101011”更改为“11010.11”。
在单精度IEEE 754中,有一个符号位(告诉我们+或-)、八个指数位和23个值位(用于“尾数”或“分数”)。指数位的值为0和255是特殊的。对于指数位的其他值,我们减去127以获得从-126(将小数点向左移动126位)到127(将小数点向右移动127位)的指数范围。尾数位被解释为二进制数字,除了我们对它们进行了一些修改:我们写下“1”,然后是一个小数点,然后是23位的尾数,因此我们有类似“1.1101011000…”的东西。作为替代方案,您可以将其视为整数:“1”然后23位没有插入小数点,形成24位的二进制数字,但指数调整了额外的23(因此减去150而不是127)。
在双精度IEEE 754中,有一个符号位、11个指数位和52个尾数位。
还有其他浮点格式,它们不太常见。一些较旧的使用十六进制作为基数(使用指数表示每次移动四位而不是一位)。十进制浮点数是一种重要的浮点数格式,其中指数表示10的幂。在十进制浮点数中,尾数可以是二进制整数,也可以是二进制编码的十进制数(其中每四个位表示一个十进制数字),或者它可以是混合格式(使用一些位来根据自定义方案表示少量的十进制数字组)。浮点数的一个重要特性是,它们不能表示所有实数(即使在有限范围内也是如此),甚至无法表示所有有理数。这迫使数学运算返回四舍五入到可表示数字的结果,这给那些不熟悉浮点运算的人带来了很多问题。这个特性又变成了十进制浮点数的一个特点:它适用于处理货币面额和其他通常以小数为单位的与人类相关的数字,因为通过仔细使用十进制浮点数可以消除大部分舍入误差。而科学家和数学家则更喜欢二进制浮点数,因为它更广泛地可用,并且得到硬件的良好支持。
计算机中还有其他表示非整数的方法。另一种常见的方法是定点数。在定点数中,将一系列位(例如1101011)解释为在已知的固定位置上的基数点。该位置应固定在特定应用程序的有用位置上。因此,位1101011可以表示数字11010.112。定点数的一个优点是,它可以使用标准硬件轻松实现。要将两个定点数相加,我们只需像将它们看作整数一样将它们相加。要将两个定点数相乘,我们将它们视为整数相乘,但结果在基数点后面有两倍多的位置,因此我们要调整位数以适应这一点,或者编写代码使得这些操作的结果被解释为已知基数点后的位数。一些处理器具有支持固定点的指令,可以通过调整乘法来实现此效果。
数字也可以缩放为整数。例如,要处理美国货币,我们只需将美元金额乘以100,并使用整数进行所有算术运算。当显示最终结果时,只插入基数点(并在从人类读取数据时解释基数点)。另一个常见的缩放方法是通过乘以255来表示像素强度(从0到1),从而使0到1的小数适合八位字节中。
还有软件提供扩展精度(使用基本算术类型的多个单元提供额外的精度)或任意精度(使用动态数量的单位提供所需的尽可能多的精度)。与硬件支持的算术相比,这样的软件非常慢,通常仅用于特殊目的。此外,扩展精度具有与浮点数完全相同的特性;仅仅是舍入误差更小,而不是消失。任意精度具有相同的缺陷,只是其动态精度可能使您将误差减小到足以获得在必要区间内的最终结果(可能需要证明已经这样做了)。
表示非整数的另一种方法是使用分数。可以存储一个分子和一个分母,并以与学校教学中相同的方式执行算术运算:通过乘法相乘分子和分母。通过将两个分数转换为具有公共分母的分数,然后加上分子来进行加法。这种算术运算很不方便,因为分母很快变大,所以需要扩展精度或任意精度来管理它们。

你也可以用符号或复合表达式来表示数字。例如,可以将2的平方根存储为表示应用于数字2的平方根操作的数据结构,而非存储数值。使用此类表示法执行除最简单的操作外的其他操作需要非常复杂的软件来管理表达式、组合它们、找到约简等。这种表示方法在专门的数学软件中使用,如Maple和Mathematica。

最后,你可以以任何想要的方式表示数字。我们现代的处理器是通用计算设备,只受其速度和存储容量的限制,因此你可以编写算法,用字符串、数据结构或任何其他技术表示数字。


5
嘿,伙计,这里是Stack Overflow。Encyclopaedia Britannica在隔壁建筑物 ;) - Tom Anderson
3
我感到恼火,因为你那条评论得到了每字节2e-2的投票,而我的答案只得到了4.3e-4。 - Eric Postpischil
@EricPostpischil,您能解释一下指数位的值0和255是特殊的吗?对于指数位的其他值,我们减去127以获得从-126(将基数点向左移动126位)到127(将基数点向右移动127位)的指数。您不是说MSB是符号位吗?负指数意味着什么? - Geek
我在这个答案中描述了IEEE 754浮点格式:http://stackoverflow.com/questions/11950343/how-is-a-float-represented-hexadecimally/11963554#11963554。 - Eric Postpischil
你应该阅读那个链接中的答案,简单来说:IEEE 754格式的符号位告诉你这个数字是正数还是负数。指数告诉你要缩放的二次幂。负指数表示非常小的数字(但如果符号位为0,则仍为正数)。大指数表示非常大的数字。 - Eric Postpischil

4

这是一个非常复杂的主题,根据所涉及的精度大小可能需要专门的硬件。

最基本的答案是它是一个x位变量 - 分为3部分 -

例如,32位FP将是:

1 bit for the sign (-/+)

8 bits for the exponent (power) of 10

23 bits for the significant numbers.

当你在单元格中输入一个很大的 FP,就像 Excel 中出现了类似于 1.23E-01 的东西时 - 这意味着将 1.23 乘以 10 的负1次幂 - 换句话说是 0.123。

因此,在二进制中,这将是:01000000011110110000000000000000

分解:

0 = sign bit - positive

010000000 - exponent - one (edit: first bit is sign bit of exponent)

11110110000000000000000 - signifant figures of 123

无论如何,这真的很粗糙,而且我的二进制知识也有点生疏,所以请有经验的人进行纠正。

+1 是为了给我直觉。这正是我想要的,而不是一些花哨几乎无法阅读的IEEE浮点数维基百科链接。 - Geek

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接