【问题标题】:How to find the minimum positive number that added to 1.0 gives something larger?如何找到添加到 1.0 的最小正数会产生更大的结果?
【发布时间】:2012-07-09 04:27:19
【问题描述】:

在将一些 Fortran 翻译成 Scheme/Racket 时,我遇到了 功能:

; EPSILON(X)      The  least  positive  number  that added
;                 to 1 returns a number that is greater than 1

如何在 Scheme 中找到号码?

【问题讨论】:

    标签: scheme racket numerical


    【解决方案1】:
    #lang racket/base
    
    ;; http://en.wikipedia.org/wiki/Machine_epsilon
    ;; approximates the machine epsilon
    
    (require racket/flonum)
    
    (define (compute-machine-epsilon)
      (let loop ([n 1.0])
        (define next-n (fl/ n 2.0))
        (if (fl= 1.0 (fl+ 1.0 next-n))
            n
            (loop next-n))))
    

    【讨论】:

    • 正确,唯一需要注意的是,这假设我们有一个基数为 2 的数字。在其他编程语言中可能存在它是 BCD 的情况。
    【解决方案2】:

    假设您使用的是 IEEE-754 浮点数(在 Scheme 中可能不是这种情况,我不知道),那么 machine epsilon 是众所周知的:对于双精度算术,它是 1.11e-16 .

    对于其他平台或浮点实现,维基百科将计算公式显示为(在 Haskell 中):

    main = print . last . map (subtract 1) . takeWhile (/= 1) . map (+ 1) . iterate (/2) $ 1
    

    【讨论】:

      【解决方案3】:

      这不是一个新的答案——只是让我感到困扰的是 Danny 的代码看起来很难做这种事情......它可以简化为

      (let loop ([n 1.0])
        (if (= 1 (+ 1 (/ n 2)))
          n
          (loop (/ n 2))))
      

      【讨论】:

      • 也许我应该说服 Neil 将 machine-epsilon 添加到球拍/数学中?
      • IIUC,有一大堆这些有用的东西,对吧?他可能已经在情节库中拥有其中一些。
      • 可能是。 Science Collection 已经有了 machine-epsilon。
      【解决方案4】:

      现有的答案是不必要的复杂,并可能导致不可移植的代码。

      正确的答案是,如 Racket 的 math/flonum package 中所述,使用 epsilon.0 值,这对于当前机器是正确的,并且不需要您手动计算:

       (require math/flonum)  
       epsilon.0
      

      【讨论】:

      • 好点。不过,数学/flonum 库在 12 年并不存在。我想我成功说服了 Neil 添加它:-)
      猜你喜欢
      • 1970-01-01
      • 2013-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多