Как найти минимальное положительное число, которое добавляется к 1,0, дает что-то большее?

При переводе некоторого Фортрана на Схему / Ракетку я натолкнулся на функцию:

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

Как мне найти номер в схеме?

4 ответа

Решение
#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))))

Предполагая, что вы используете IEEE-754 с плавающей точкой (что может быть не так в Схеме, я не знаю), тогда машинный эпсилон хорошо известен: для арифметики двойной точности это 1.11e-16,

Для других платформ или реализаций с плавающей запятой, Википедия показывает формулу для вычисления этого как (в Haskell):

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

Это не новый ответ - меня просто беспокоит, что из-за кода Дэнни кажется, что это трудно сделать, такого рода вещи... его можно упростить до

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

Существующие ответы излишне сложны и могут привести к непереносимому коду.

Правильный ответ, как задокументировано в пакете math / flonum Racket, заключается в использовании значения epsilon.0, которое будет правильным для текущей машины и которое не потребует от вас вычисления вручную:

 (require math/flonum)  
 epsilon.0
Другие вопросы по тегам