5

出于这个问题的目的,我没有使用printf设施的能力(不幸的是,我不能告诉你为什么,但现在让我们假设我知道我在做什么)。

对于 IEEE754 单精度数,您有以下位:

SEEE EEEE EFFF FFFF FFFF FFFF FFFF FFFF

其中S是符号,E是指数,F是分数。

在所有情况下打印符号都相对容易,因为捕获所有特殊情况,如NaN( E == 0xff, F != 0)、Inf( E == 0xff, F == 0) 和0( E == 0, F == 0,被认为是特殊的,因为在这种情况下不使用指数偏差)。

我有两个问题。

首先是如何最好地将非规范化数字(哪里E == 0, F != 0)转换为规范化数字(哪里1 <= E <= 0xfe)?我怀疑这对于简化下一个问题的答案是必要的(但我可能是错的,所以请随时教育我)。

第二个问题是如何打印出标准化的数字。我希望能够以两种方式将它们打印出来,指数类-3.74195E3和非指数类3741.95。虽然,只是并排看这两个,通过移动小数点应该很容易将前者变成后者。所以让我们只关注指数形式。

我对我很久以前用于打印 PI 的算法有一个模糊的回忆,其中您使用了一个不断减少的公式并保持可能性的上限和下限,当两个限制一致时输出一个数字,并将计算转移因子 10(因此当上限和下限为3.23643.1234时,您可以3在计算中输出和调整)。

但是我已经很久没有这样做了,所以我什至不知道这是否适合在这里采取。似乎是这样,因为当通过小数部分(1/21/41/8)时,每个位的值是前一个位的一半。

除非绝对必要,否则我真的希望不必费力地阅读printf源代码,因此,如果有人可以提供帮助,我将永远感激不尽。

4

4 回答 4

3

如果您想获得每次转换的准确结果,则必须使用任意精度的算术,就像在 printf() 实现中所做的那样。如果您想获得“接近”的结果,可能仅在它们的最低有效位上有所不同,那么一个非常简单的基于双精度的算法就足够了:对于整数部分,重复除以十并将余数附加到形成十进制字符串(反向);对于小数部分,重复乘以十并减去整数部分以形成十进制字符串。

我最近写了一篇关于这种方法的文章:http ://www.exploringbinary.com/quick-and-dirty-floating-point-to-decimal-conversion/ 。它不打印科学记数法,但添加起来应该很简单。该算法打印次正规数(我打印的数字准确无误,但您必须进行更彻底的测试)。

于 2010-11-25T16:03:39.927 回答
1

非规范化数字不能转换为相同浮点类型的规范化数字。等效归一化数的指数太小而无法用指数表示。

要打印标准化数字,我能想到的一种愚蠢方法是重复乘以 10(好吧,对于小数部分)。

于 2010-11-25T08:20:55.110 回答
0

您需要做的第一件事是使用对数将指数转换为十进制(因为大概这就是您想要的输出)。您取该结果的分数并将尾数乘以该分数的 exp10,然后将其转换为十进制字符。从那里你只需要在适当的位置插入小数点,移动现在的十进制指数。

于 2010-11-25T08:22:43.403 回答
0

G. Steele 的一篇论文更详细地描述了一种算法,该算法似乎基于与您概述的相同原理。如果内存服务,有时您会被迫使用无界精度算术。(我认为它是如何准确打印浮点数,但目前 citeseer 从这里开始下降,我无法确认,谷歌的结果被 20 年后的回顾论文污染了)。

于 2010-11-25T09:23:24.310 回答