将分数部分转换为二进制

Posted

技术标签:

【中文标题】将分数部分转换为二进制【英文标题】:Convert Fraction Part to Binary 【发布时间】:2015-09-30 20:19:34 【问题描述】:

我有一个浮点数的一小部分(例如,-10.5 中的 5 个)。这是一个字符,因为我从输入中提取了它。如何将该字符转换为该浮点数的二进制小数部分? (我正在构建一个浮点输入-> 32 位 IEEE784 中的十六进制输出,我已经提取了尾数的符号、指数和整数部分的二进制表示。)

我一直在考虑实现将分数乘以 2 并取余数,然后重复直到填满尾数的算法,但我不允许在赋值中使用任何浮点运算。

示例: 用户输入 -10.5。程序需要取数字的小数部分(即5),并将其转换为二进制格式(即1(.1))

编辑:我受到 16 位寄存器大小的限制,因此我需要一个解决方案来对 > 2^16-1 的数字进行操作。

【问题讨论】:

问题不是很清楚。请展示一些典型的输入,它们是如何获得的,以及每种情况下所需的输出。和代码(“我已经提取...”) 目前,我有两个 32 位内存字,长型数字,一个是 1(因为符号是负数),另一个是二进制的 10。我也有字符数组 '5' 作为第一个也是唯一一个元素。它是所提供数字的分数(可以是“05”、“00001257852”等)。我只需要将其转换为位。 ...在问题中,请不要像华夫饼那样。 【参考方案1】:

您的想法基本上是正确的。只需将小数部分加倍,进位就变成了数字。以.7转二进制为例(.5太简单了)

NUMBER REMAINDER CARRY
    .7       ---     .
   1.4        .4     1
    .8        .8     0
   1.6        .6     1
   1.2        .2     1
    .4        .4     0
    .8        .8     0
   1.6        .6     1
   1.2        .2     1
&ct.

所以二进制中的.7.101100110...10.7 就是1010.101100110...

一旦余数变为0,或者由于 IEEE 浮点精度的限制,总表示变为 24 位长,您就可以停止转换为二进制。

请注意,小数本身纯粹是装饰性的,这里没有使用浮点数。

NUMBER     %10    /10
     7     ---      .
    14       4      1
     8       8      0
    16       6      1
    12       2      1
     4       4      0
     8       8      0
    16       6      1
    12       2      1
&ct.

.07 的情况下,您将表示余数并分别由%100/100 进位。对于.007,您将使用%1000/1000

【讨论】:

非常感谢!我会立即尝试实施解决方案,太棒了!【参考方案2】:

在 IEEE-754 的意义上,浮点数的小数部分在整数的上下文之外没有明确定义的含义。区分值10.5 和值10.0 的位比区分值0.0 和值0.5 的位是整个表示的较小子集。当谈论 IEEE-754 数字表示的“分数”部分时,通常是在谈论尾数的所有位。对于 24 位的 IEEE 754 单精度二进制格式,包括一个隐含位,无论数字的大小如何。

更新/修订:

根据澄清问题的更新,我已经替换了我之前的大部分答案,它解决了以编程方式提取 floatdouble 的位的问题,而不是转换十进制格式 text 表示为 IEEE-754 格式表示的位。正如我在这个答案的原始版本中所说的那样,解析文本是一个棘手的问题。

我仍然重申,我认为将尾数分成单独的部分是错误的。它没有提供我可以看到的特别优势,但它引入了稍后正确重新组合片段的问题。

这是解决整个问题的可行方法:

    根据有无负号判断输入数的符号。

    形成输入数字绝对值的大数表示。例如,以 1,000,000,000 为基数的表示形式,存储在 uint32_t 的数组中。只要底数是 10 的幂,就可以直接将十进制格式的输入数字解析为这种表示形式,并且不会引入舍入误差。

    将 bignum 表示按适当的 2 次方缩放以获得介于 223 和 224 - 1 之间的缩放值。这只能通过整数运算。请注意,您可能需要按比例缩小而不是放大。无论哪种方式,这种缩放都可以单独通过整数算术来执行。请记住使用 2 的幂 (s) 作为比例因子(即比例因子的以 2 为底的对数,而不是比例因子本身;这可以很容易地从算法中得出,无需计算超越函数必填)。

    四舍五入到单位精度。

然后,您将获得步骤 1 中的符号位,尾数/有效位的位作为 bignum 的剩余有效位(请记住,在最终的 IEEE 格式中,最高有效位是隐式的,而不是显式的),以及指数为23 - s

还要注意,这种方法可以非常自然地扩展到科学记数法。

【讨论】:

谢谢,可悲的是,有些大学教授缺乏常识。我的想法是由我大学的一个已经处理过这项任务的人提出的,分别翻译整数和小数部分(这就是我要做的)。我会将它们放入 32 位存储字(符号字、指数字、尾数字)中,如果需要移位并添加到寄存器中。然后我会以某种方式打印出所有内容。 好吧,请注意 32 位可能还不够。您可能需要少至零或多至 53(同样,对于 IEEE 二进制双精度)来表示具有大于单位精度的数字大小的部分。还要注意正确舍入不完全可表示的数字的结果。 我明白,但我并不关心四舍五入等。我只需要在 23 位尾数中添加尽可能多的数字(它实际上不是记忆词,更多的是词的一部分)直到它满了。 @LukasValatka,我已经用一个旨在解析文本而不是分析现有浮点表示的答案替换了我之前的大部分答案。你需要一些类似的东西来正确处理所有可能的输入,例如,那些大于 32 位整数可以表示的输入。 如果您需要更多详细信息,我已在 exploringbinary.com/… 上写过有关该算法的详细信息

以上是关于将分数部分转换为二进制的主要内容,如果未能解决你的问题,请参考以下文章

十进制小数分数与二进制之前的转换

将字符串转换为十进制,保留分数

将十进制数转换为分数 AS3

十进制的分数如何转成二进制的?

LeetCode 405. 数字转换为十六进制数(补码的问题) / 166. 分数到小数(模拟长除法) / 482. 密钥格式化

小时转换成小数点