十进制浮点包

时间:2012-10-10 11:35:23

标签: common-lisp gnu-common-lisp

我理解使用二进制(或二进制)浮点并以十进制表示结果时的复杂性:

1 (do ((numerator 1 (* 10 numerator)))
 2     ((>= numerator 1000000000000))
 3   (let ((fred (list 'coerce (/ numerator 3) (quote 'double-float))))
 4     (prin1 fred)
 5     (princ " ")
 6     (prin1 (eval fred))
 7     (terpri)))
(COERCE 1/3 'DOUBLE-FLOAT) 0.3333333333333333d0
(COERCE 10/3 'DOUBLE-FLOAT) 3.3333333333333335d0
(COERCE 100/3 'DOUBLE-FLOAT) 33.333333333333336d0
(COERCE 1000/3 'DOUBLE-FLOAT) 333.3333333333333d0
(COERCE 10000/3 'DOUBLE-FLOAT) 3333.3333333333335d0
(COERCE 100000/3 'DOUBLE-FLOAT) 33333.333333333336d0
(COERCE 1000000/3 'DOUBLE-FLOAT) 333333.3333333333d0
(COERCE 10000000/3 'DOUBLE-FLOAT) 3333333.3333333335d0
(COERCE 100000000/3 'DOUBLE-FLOAT) 3.3333333333333332d7
(COERCE 1000000000/3 'DOUBLE-FLOAT) 3.333333333333333d8
(COERCE 10000000000/3 'DOUBLE-FLOAT) 3.3333333333333335d9
(COERCE 100000000000/3 'DOUBLE-FLOAT) 3.3333333333333332d10

但我希望避免最后变数的不足之处。在这种情况下,计算速度对我来说并不重要。

那里是否存在任何真正的十进制浮点LISP包?

编辑1 :理想情况下,此包允许任意精度,正如bignum对整数所做的那样。

编辑2 ,以回应Dennis Jaheruddin提出的问题:

  

[我]你对最后的数字不感兴趣,但只是想要   数字是相同的,你可能只想观察前15或   那么数字?

我想到了这一点。它不会起作用。例如,在2/3的情况下,我想要像666667这样的东西。我看到的是:

 1 (do ((numerator 2 (* 10 numerator)))
 2     ((>= numerator 1000000000000))
 3   (let ((fred (list 'coerce (/ numerator 3) (quote 'double-float))))
 4     (prin1 fred)
 5     (princ " ")
 6     (prin1 (eval fred))
 7     (terpri)))
(COERCE 2/3 'DOUBLE-FLOAT) 0.6666666666666666d0
(COERCE 20/3 'DOUBLE-FLOAT) 6.666666666666667d0
(COERCE 200/3 'DOUBLE-FLOAT) 66.66666666666667d0
(COERCE 2000/3 'DOUBLE-FLOAT) 666.6666666666666d0
(COERCE 20000/3 'DOUBLE-FLOAT) 6666.666666666667d0
(COERCE 200000/3 'DOUBLE-FLOAT) 66666.66666666667d0
(COERCE 2000000/3 'DOUBLE-FLOAT) 666666.6666666666d0
(COERCE 20000000/3 'DOUBLE-FLOAT) 6666666.666666667d0
(COERCE 200000000/3 'DOUBLE-FLOAT) 6.6666666666666664d7
(COERCE 2000000000/3 'DOUBLE-FLOAT) 6.666666666666666d8
(COERCE 20000000000/3 'DOUBLE-FLOAT) 6.666666666666667d9
(COERCE 200000000000/3 'DOUBLE-FLOAT) 6.6666666666666664d10

正如你所看到的,我甚至无法使用最后的数字来决定是否进行整理; 64轮到60轮,而不是70轮。但我可以丢弃最后一个数字并使用前一个数字来围绕数字的其余部分。不过,我对此感到不舒服,因为(a)我现在开始放弃很多精确度,而且(b)我不确定是否有这种情况这会导致错误的方式四舍五入。十进制浮点包,最好具有任意精度,是理想的。

编辑3 :正如Rainer Joswig在下面的回答中指出的那样,非便携式潜在解决方案是设置浮点精度。对于那些在家中跟随的人,他指出here这样做是这样的:(SETF (EXT:LONG-FLOAT-DIGITS) n)

编辑4 :在回答后的评论中,Rainer Joswig建议研究代数系统Maxima和Axiom。这样做会带来这些优秀的维基百科资源:

编辑5:我已经确定我不需要十进制浮点包,但我仍然很好奇是否有一个。可能没有。

为什么我不需要?答案是(a)Rainer Joswig指向wu-decimal包的指针和(b)wvxvw提到的长除法的组合。

尽管wu-decimal没有使用基数10的常规特征和尾数,但它确实引入了一个有趣的想法:将数字存储为比率。因此1/3存储为1/3,而不是重复(对于有限长度)二进制分数。尽管存储为比率的数字乘以很快会产生相当长的比率,但始终保持原始精度。我会使用这个想法。我不需要的是wu-decimal非常漂亮的解析和编写适当的十进制数字比例,所以我不会安装包。如果您有兴趣轻松解析和编写此类值,请查看包。 (我还没用过它。)

然后,剩下的是将比率打印为十进制数。为此,我将使用长分区,就像wvxvw一样。我的代码有些不同,但对于长期分工的想法,我非常感谢他。

1 个答案:

答案 0 :(得分:1)

从未使用过它:

http://wukix.com/lisp-decimals

在GNU CLISP中,您可以设置浮点精度。