Six*_*s17 5 scheme scientific-notation arithmetic-expressions racket
我试图对两个非常大的数字进行简单的减法运算.
(- 1.8305286640724363e+023 (floor 1.8305286640724363e+023))
Run Code Online (Sandbox Code Playgroud)
当我这样做时,我得到0.0的结果.我期待输出:
(- 1.8305286640724363e+023 (floor 1.8305286640724363e+023)) => .2439521
Run Code Online (Sandbox Code Playgroud)
扩展的科学记数法会给我答案.
183052866407243622723319.24395251 - 183052866407243622723319.00 = .2439521
我想用这些数字来表示这些数字,使用十进制数字,而不是科学记数法,所以我可以达到预期的结果.在Scheme中有没有办法做到这一点?任何帮助,指导或参考将不胜感激:)
我正在使用DrRacket for Windows 64bit和R5RS Language.
编辑
我想我会尽可能具体地说明我正在执行的算术的例子.
算术:
(* 271979577247970257395 0.6180339887) => 1.6809262297150285e+020
Run Code Online (Sandbox Code Playgroud)
当在计算器中进行相同的乘法时,结果yeilds => 168092622971502827156.7975214365
当试图使用精确或不精确时我得到这个:
(exact (* 271979577247970257395 0.6180339887)) => exact: undefined;
(inexact (* 271979577247970257395 0.6180339887)) => inexact: undefined;
Run Code Online (Sandbox Code Playgroud)
我想R5RS不支持精确/不精确?我查了一下,示例显示使用不精确 - >精确的程序所以我做了并得到了这个:
(inexact->exact (* 271979577247970257395 0.6180339887)) => 168092622971502854144
Run Code Online (Sandbox Code Playgroud)
仅仅为了特异性,我做了相反的事情:
(exact->inexact (* 271979577247970257395 0.6180339887)) => 1.6809262297150285e+020
Run Code Online (Sandbox Code Playgroud)
所以我尝试使用Big Float,就像有人提到的那样:
(bf-precision 128)
(bf (* 271979577247970257395 0.6180339887)) => (bf 168092622971502854144)
Run Code Online (Sandbox Code Playgroud)
给我完全相同的输出.我只想要保存得到我从计算器得到的数字,这似乎是一项非常艰巨的任务!对不起,我可能因为没有得到这个而听起来很愚蠢,请记住我在计划中是一个极端的业余爱好者.再次感谢你的帮助!:)
问题在于输入中的有效数字比 Racket 在其内部表示中使用的数字还要多。
让我们输入简单的数字:
> 183052866407243622723319.24395251
1.8305286640724363e+23
> 183052866407243622723319.00
1.8305286640724363e+23
Run Code Online (Sandbox Code Playgroud)
因此,两个数字在内部都表示为相同的(整数)数字。这解释了为什么你的结果是 0。
这种行为不仅限于 Racket。事实上,Racket 遵循 IEEE 标准来计算 64 位浮点数。在其他编程语言中您将得到相同的结果。
如果您需要计算为什么精度更高,您可以使用 bigfloats 代替。
(require math/bigfloat)
(bf-precision 128) ; use 128 bits
(bf- (bf #e183052866407243622723319.24395251)
(bfround (bf #e183052866407243622723319.00)))
Run Code Online (Sandbox Code Playgroud)
结果是:(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))))
Run Code Online (Sandbox Code Playgroud)
结果是:0.24395251
附录:
Racket(和Scheme)将带有小数点的数字读取为浮点数。如果您在数字前加上#e,它将被读取为精确数字(即结果值是精确分数)。您可以使用它来保留精确的小数。您对整个计算进行精确计算,然后最终将exact->inexact结果转换为浮点数。这是你的例子:
> (exact->inexact
(- #e183052866407243622723319.24395251
#e183052866407243622723319.00))
0.24395251
Run Code Online (Sandbox Code Playgroud)