如何在计算机中表示分数?

时间:2012-08-17 13:20:14

标签: java language-agnostic floating-point bits fractions

由于计算机以“1”和“0”的形式思考,它们如何计算和表示7.50等分数?我知道Java和JavaScript,如果答案需要,你可以用它们作为例子。

编辑:我在46:31秒观察了这个MIT video on hashing by Prof. Cormen他使用模块化轮子解释了乘法散列函数,模块化轮子是一个单位圆圈,其中有几个点,这些点表示分数。这促使我在SO中提出这个基本问题。

3 个答案:

答案 0 :(得分:10)

在计算机上表示除整数之外的数字的最常用方法是使用浮点数,尤其是IEEE 754浮点数。您可能熟悉的是,整数通常用硬件位来表示二进制数字,因此物理属性(如充电或缺电,高压或低压,一个方向或另一个方向的磁场)用于表示位(0和1),这些位的序列产生一个数字(例如11010),我们用二进制解释它来表示一个数字(11010 2 是16 + 8 + 2 = 26 )。我们通常不会想到它,但是在这个数字的右边有一个“小数点”:“11010。”当我们右边有更多位时,我们只需要小数点,它代表分数。例如,11010.11 2 是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.11 2 。定点的一个优点是它可以使用标准硬件轻松实现。要添加两个定点数,我们只需将它们添加为整数。为了将两个定点数相乘,我们将它们相乘,就好像它们是整数一样,但结果在小数点之后的位置是两倍,所以我们要么移位这些位来调整,要么我们编写代码以便结果这些操作用小数点后的已知位数来解释。某些处理器通过调整此效应的乘法来指示支持定点。

数字也可以缩放为整数。例如,要使用美国货币,我们只需将美元金额乘以100,并使用整数进行所有算术运算。小数点仅在显示最终结果时插入(并在从人类读取数据时进行解释)。另一种常见的缩放是通过乘以255来表示像素强度(从0到1),因此从0到1的分数适合8位字节。

还有软件可以提供扩展精度(使用基本算术类型的几个单位来提供额外的精度)或任意精度(使用动态数量的单位来提供所需的精度)。与硬件支持的算法相比,此类软件非常慢,通常仅用于特殊目的。另外,扩展精度与浮点具有基本相同的属性;只是圆角误差较小,没有消失。任意精度都有相同的缺陷,除了它的动态精度可能允许你使误差足够小,你可以获得一个必要的间隔内的最终结果(证明你已经这样做了)。

表示非整数的另一种方法是使用分数。您可以存储分子和分母,并以与学校教授的方式相同的方式执行算术:乘以分子和乘以分母。通过将两个分数转换为具有公分母来添加,然后添加分子。这种算法是有问题的,因为分母很快变大,所以你需要扩展的精度或任意精度来管理它们。

您还可以用符号或复合表达式表示数字。例如,您可以使用表示应用于数字2的平方根操作的数据结构来存储它,而不是将2的平方根存储为数字值。使用此类表示执行任何但最简单的操作需要非常复杂的软件管理表达式,组合它们,查找减少量等等。这种表示用于专业数学软件,如Maple和Mathematica。

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

答案 1 :(得分:3)

这是一个非常复杂的主题,可能需要专业硬件,具体取决于所涉及的精度。

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

例如,32位FP将是:

1 bit for the sign (-/+)

8 bits for the exponent (power) of 10

23 bits for the significant numbers.

当你把一个巨大的FP放入一个单元格并且它做了类似1.23E-01之类的东西时想想Excel - 这意味着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

无论如何这真的很粗糙,我的二进制文件生锈了,所以有人请纠正错误。

答案 2 :(得分:1)

有趣的是我最近在阅读相同的主题,因为我正在处理一些财务问题,需要做浮点运算。我强烈建议您阅读文章What Every Computer Scientist Should Know About Floating-Point Arithmetic

另请参阅软件中浮点的this post by Joel Spolsky