java - 分数在计算机中是如何表示的?

标签 java language-agnostic floating-point bits fractions

由于计算机根据“1”和“0”进行思考,它们如何计算和表示诸如 7.50 之类的分数?我知道 Java 和 JavaScript,如果需要答案,您可以将它们用作示例。

编辑 : 我在看这个MIT video on hashing by Prof. Cormen在 46:31 秒,他使用模轮解释了乘法哈希函数,模轮是一个单位圆,里面有几个点,点表示分数。这促使我在 SO 中提出这个基本问题。

最佳答案

在计算机上表示除整数以外的数字的最常用方法是使用浮点数,尤其是 IEEE 754 浮点数。您可能熟悉,整数通常使用硬件位来表示二进制数字,因此物理属性(例如带电或不带电、高电压或低电压、一个方向或另一个方向的磁场)用于表示表示位(0 和 1),这些位的序列构成一个数字(例如 11010),我们将其解释为二进制以表示一个数字(110102 是 16+8+2 = 26)。我们通常不会想到它,但在这个数字的右侧有一个“小数点”:“11010”。当小数点右边有更多位时,我们只需要小数点,代表分数。例如,11010.112 是 16 + 8 + 2 + 1/2 + 1/4 = 26.75。为了从整数变为浮点数,我们使小数点 float 。除了代表数字的位之外,我们还有一些额外的位来告诉我们将小数点放在哪里。

所以,我们可能有三位,比如 010,表示小数点的位置,其他位,比如 1101011,表示值。小数点位 010 可能表示将小数点向左移动两个位置,更改为“1101011”。到“11010.11”。

在单精度 IEEE 754 中,有 1 个符号位(告诉我们 + 或 -)、8 个指数位和 23 个值位(用于“有效数”或“小数”)。指数位的值 0 和 255 是特殊的。对于指数位的其他值,我们减去 127 以获得范围从 -126(小数点左移 126 位)到 127(小数点右移 127 位)的指数。有效数位被解释为二进制数字,除了我们稍微修改它们:我们写“1”,然后是小数点,然后是有效数的 23 位,所以我们有类似“1.1101011000...”的东西。作为替代方案,您可以将其视为整数:“1”然后是 23 位,没有插入小数点,构成一个 24 位二进制数字,但指数调整了额外的 23(因此减去 150 而不是 127) .

在 double IEEE 754 中,有 1 个符号位、11 个指数位和 52 个有效位。

还有其他不太常见的浮点格式。一些较旧的使用十六进制作为基数(使用指数表示四位而不是一位的移位)。浮点格式的一种重要类型是十进制,其中指数表示 10 的幂。在十进制浮点中,有效位可以是二进制整数,也可以是二进制编码的十进制数(其中每四位表示一个十进制数字) ) 或者它可以是混合的(根据自定义方案,位组用于指示少量十进制数字)。

浮点数的一个重要特性是它们不能表示所有实数(当然,即使在有限范围内)甚至所有有理数。这迫使数学运算返回四舍五入为可表示数字的结果,这对于不熟悉浮点运算的人来说是无穷无尽的。此属性反过来成为十进制浮点数的一个特性:它适用于处理货币面额和其他通常以十进制操作的与人类相关的数字,因为可以通过谨慎使用十进制浮点数来消除大多数舍入错误。科学家和数学家更多地研究与自然相关的或纯数字而不是人类污染的数字,他们倾向于更喜欢二进制浮点数,因为它更广泛可用并且得到了硬件的良好支持。

还有其他方法可以在计算机中表示非整数。另一种常用的方法是定点。在定点中,位序列(例如 1101011)用位于已知固定位置的小数点进行解释。该位置将固定在对特定应用有用的位置。所以位 1101011 可以代表数字 11010.112。定点的一个优点是它很容易用标准硬件实现。要将两个定点数相加,我们只需将它们作为整数相加即可。为了将两个定点数相乘,我们把它们当做整数相乘,但结果在小数点之后的位置是原来的两倍,所以我们要么移动位来调整这个,要么我们编写代码使得结果此类操作使用小数点后的已知位数进行解释。一些处理器有通过调整乘法来支持定点的指令。

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

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

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

您还可以用符号或复合表达式来表示数字。例如,不是将 2 的平方根存储为数值,您可以将其与表示应用于数字 2 的平方根运算的数据结构一起存储。使用此类表示执行除最简单运算之外的任何运算都需要非常复杂的软件才能管理表达式,组合它们,找到减少,等等。这种表示用于专门的数学软件,例如 Maple 和 Mathematica。

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

关于java - 分数在计算机中是如何表示的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12006635/

相关文章:

java - Spring3排除绑定(bind)表单字段

Java REST 服务二进制文件下载

c++ - 这是使用宏的好方法吗?

java - 浮点精度在实际例子中到底如何工作?

C++ 双除法并返回

python - 下面的二次方程代码有什么问题?

java - 在没有渲染器的情况下更改 JComboBox 颜色

java - Spring Mvc 从表中提交/删除选中(选中)的记录

algorithm - 在二叉树中找到两个最远的元素

math - float 学有问题吗?