科学记数法转换 - 计划

时间:2013-04-15 06:42:15

标签: scheme racket scientific-notation arithmetic-expressions

我正在尝试对两个非常大的数字进行简单的减法运算。

(- 1.8305286640724363e+023 (floor 1.8305286640724363e+023))

当我这样做时,我得到0.0的结果。我期待输出:

(- 1.8305286640724363e+023 (floor 1.8305286640724363e+023)) => .2439521

扩展的科学记数法会给我答案。

183052866407243622723319.24395251 - 183052866407243622723319.00 = .2439521

我想用这些数字来表示这些数字,使用十进制数字,而不是科学记数法,所以我可以达到预期的结果。在Scheme中有没有办法做到这一点?任何帮助,指导或参考将非常感谢:)

我正在使用DrRacket for Windows 64bit和R5RS Language。

编辑

我认为我会尽可能具体地说明我正在执行的算术示例。

算术:

(* 271979577247970257395 0.6180339887) => 1.6809262297150285e+020

在计算器中进行相同的乘法时,结果yeilds => 168092622971502827156.7975214365

当尝试使用精确或不精确时,我得到了这个:

(exact (* 271979577247970257395 0.6180339887)) => exact: undefined;
(inexact (* 271979577247970257395 0.6180339887)) => inexact: undefined;

我认为R5RS不支持精确/不精确?我查了一下,示例显示使用不精确的>精确的程序,所以我做了并得到了这个:

(inexact->exact (* 271979577247970257395 0.6180339887)) => 168092622971502854144

仅仅为了特异性,我做了相反的事情:

(exact->inexact (* 271979577247970257395 0.6180339887)) => 1.6809262297150285e+020

然后我尝试使用Big Float,就像有人提到的那样:

(bf-precision 128)
(bf (* 271979577247970257395 0.6180339887)) => (bf 168092622971502854144)

给我相同的输出。我只想要保存得到我从计算器得到的数字,这似乎是一项非常艰巨的任务!对不起,我可能因为没有得到这个而听起来很愚蠢,请记住我在计划中是一个极端的业余爱好者。再次感谢你的帮助! :)

2 个答案:

答案 0 :(得分:4)

问题是输入中的有效位数比 Racket在其内部表示中使用。

让我们输入裸号:

> 183052866407243622723319.24395251
1.8305286640724363e+23

> 183052866407243622723319.00
1.8305286640724363e+23

因此,两个数字在内部表示为相同(整数)。 这就解释了为什么你的结果是0。

此行为不仅限于Racket。事实上,Racket遵循IEEE标准,使用64位浮点数进行计算。您将在其他编程语言中获得相同的结果。

如果你需要计算为什么更高的精度,你可以使用bigfloats。

(require math/bigfloat)
(bf-precision 128) ; use 128 bits
(bf- (bf #e183052866407243622723319.24395251)
     (bfround (bf #e183052866407243622723319.00)))

结果是:     (bf#e0.2439525099999997337363311089575290679932)

注意:要使用bigfloats,请确保您拥有最新版本的Racket。

更新:万一你想知道为什么结果不是.2439521 答案是结果和.2439521由相同的内部位模式表示。

更新

如果要将结果转回标准浮点,请使用bigfloat->flonum

(bf-precision 256)  ; to get more decimal digits correct
(bigfloat->flonum
   (bf- (bf #e183052866407243622723319.24395251)
        (bfround (bf #e183052866407243622723319.00))))

这给出了结果:0.24395251

附录:

Racket(和Scheme)读取带小数点的数字作为浮点数。如果使用#e为数字加前缀,则将其作为精确数字读取(即结果值是精确分数)。您可以使用它来保持精确的小数。您确定整个计算的确切数字,然后最后使用exact->inexact将结果转换为浮点数。这是你的例子:

> (exact->inexact 
     (- #e183052866407243622723319.24395251
        #e183052866407243622723319.00))
0.24395251

答案 1 :(得分:4)

当然,使用Scheme,您可以得到确切的数字:

(define x (+ (exact 183052866407243622723319) (exact .24395251)))
(define y (+ (exact 183052866407243622723319) (exact .0)))

我拆分x以避免让Scheme读取器截断该值。然后:

> x
3297587283763054256749149618043779713285/18014398509481984
> (- x y)
4394657732528389/18014398509481984
> (inexact (- x y))
0.24395251

[edit]您需要在整个计算过程中使用确切的数字。这意味着将输入转换为精确,然后在不精确的情况下转换输出(如果需要)。

至于您在#e(* 27... 0.6...)的尝试 - 由于#e适用于数字而非表达式,因此无效。使用(* #e27... #e0.6...)

> (* #e271979577247970257395 #e0.6180339887)
336185245943005654313595042873/2000000000