【问题标题】:Scientific Notation Conversion - Scheme科学计数法转换 - 方案
【发布时间】:2013-04-07 05:03:57
【问题描述】:

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

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

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

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

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

183052866407243622723319.24395251 - 183052866407243622723319.00 = .2439521

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

我正在使用适用于 Windows 64 位和 R5RS 语言的 DrRacket。

编辑

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

算术:

(* 271979577247970257395 0.6180339887) => 1.6809262297150285e+020

在计算器中进行同样的乘法运算时,结果为 => 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)

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

【问题讨论】:

    标签: scheme racket scientific-notation arithmetic-expressions


    【解决方案1】:

    问题是输入中的有效数字多于 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
    

    【讨论】:

    • 您好,感谢您的及时回复! bigfloat 没有给我想要的小数位。我看到你强行告诉它小数位,然后做减法。我正在做算术来检索浮点数。我会更新问题,以便向您展示。
    • 嗨。我添加了一个更新,显示了如何将结果转换回标准浮点数。
    • 我添加了使用 bigfloats 的替代方法。
    • 我了解大型花车的工作原理,感谢您的回复。但是,问题是首先生成 183052866407243622723319.24395251 数字。我尝试添加 #e(* 271979577247970257395 0.6180339887) 但 #e 无法识别。 ://
    • #e183052866407243622723319.24395251 #e 是精确数字语法的一部分。因此你可以写 (* #e1.2 #e3.4),但你不能写 #e(* ... 因为 (* 不是数字开头。
    【解决方案2】:

    当然,使用 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
    

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

    至于你在#e(* 27... 0.6...) 的尝试——那是行不通的,因为#e 适用于数字,而不是表达式。使用(* #e27... #e0.6...)

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

    【讨论】:

    • 您将小数位显式添加到大数字中。尽管这个例子启发了我一些关于不精确和不精确的使用我不知道的事情,但我试图通过算术生成那个十进制数。看我的更新。不过还是谢谢你的回复!
    • 我明确添加了小数点,因为如果我只是将其键入为浮点数,那么当我应用 exact 时为时已晚。解决方案是使用#e 作为号码本身的前缀。注意:见上面的编辑。
    • 感谢您的更新!在您的帮助下,我找到了解决此问题的方法!非常感谢 GoZoner!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-09
    • 1970-01-01
    • 2011-11-19
    • 2012-06-22
    • 1970-01-01
    • 2015-12-27
    • 1970-01-01
    相关资源
    最近更新 更多