出于这个问题的目的,我不能够使用printf
设施(不幸的是,我无法告诉你原因,但我们现在假设我知道我在做什么。
对于IEEE754单精度数,您有以下位:
SEEE EEEE EFFF FFFF FFFF FFFF FFFF FFFF
其中S
是符号,E
是指数,F
是分数。
打印标志对于所有情况都相对容易,就像捕捉所有特殊情况一样,例如NaN
(E == 0xff, F != 0
),Inf
(E == 0xff, F == 0
)和{{1 } {(0
,被认为是特殊的,因为在这种情况下不使用指数偏差)。
我有两个问题。
第一个是如何最好地将非规范化数字(其中E == 0, F == 0
)转换为规范化数字(其中E == 0, F != 0
)?我怀疑这对于简化下一个问题的答案是必要的(但我可能是错的,所以请随时教育我)。
第二个问题是如何打印出标准化数字。我希望能够以两种方式打印它们,指数如1 <= E <= 0xfe
和非指数如-3.74195E3
。虽然,只要看看这两个并排,通过移动小数点就可以很容易地将前者转变为后者。所以我们只关注指数形式。
我对我很久以前用于打印PI的算法进行了模糊的回忆,其中你使用了一个不断减少的公式,并对可能性保持上限和下限,在两个限制达成一致时输出数字,以及转移计算系数为10(因此,当上限和下限分别为
3741.95
和3.2364
时,您可以输出3.1234
并在计算中进行调整。但是自从我这么做以来,这是很长的时间,所以我甚至不知道这是否适合采取这种方式。似乎是这样,因为当通过小数部分(
3
,1/2
,1/4
等等)时,每个位的值是前一位的一半。
我真的更喜欢 not 除非绝对必要,否则必须跋涉1/8
源代码,如果有人能帮忙解决这个问题,我将永远感激。
答案 0 :(得分:3)
如果要获得每次转换的精确结果,则必须使用任意精度算法,就像在printf()实现中一样。如果你想得到“接近”的结果,或许只有它们的最低有效数字不同,那么一个非常简单的基于双精度的算法就足够了:对于整数部分,重复除以10并将余数附加到形成十进制字符串(反向);对于小数部分,重复乘以10并减去整数部分以形成十进制字符串。
我最近写了一篇关于这种方法的文章:http://www.exploringbinary.com/quick-and-dirty-floating-point-to-decimal-conversion/。它不打印科学记数法,但这应该是微不足道的补充。该算法打印出次正规数字(我打印的数字准确无误,但您必须进行更全面的测试)。
答案 1 :(得分:1)
非规范化数字不能转换为相同浮点类型的规范化数字。等效的标准化数字的指数太小而无法用指数表示。
要打印标准化数字,我能想到的一个愚蠢的方法是重复乘以10(好吧,对于小数部分)。
答案 2 :(得分:0)
您需要做的第一件事是使用对数将指数转换为十进制(因为可能是您想要的输出)。您获取该结果的分数并将尾数乘以该分数的exp10,然后将其转换为十进制字符。从那里你只需要在适当的位置插入小数点,移动到now-decimal指数。
答案 3 :(得分:0)
G.斯蒂尔有一篇论文更详细地描述了一种似乎基于与你所概述的原理相同的算法。如果内存服务,有时候你被迫使用无界精度算术。 (我认为它是如何准确地打印浮点数但是citeseer目前已经从这里下来了,我无法确认和谷歌的结果被20年后的回顾性论文污染了)