Как найти минимальное положительное число, которое добавляется к 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