作为溢出浮点的一种简单方法(我在我的代码中使用双浮点数,所以我在这里也这样做):
(setq *read-default-float-format* 'double-float)
(defun example-float-overflow (x)
(example-float-overflow (* x x)))
(example-float-overflow 4.4)
很快,x变得越来越大。很快它达到了5.295234290518905e164并且溢出。哪个,甚至是双浮动了?
无论如何,在溢出之前识别点的最佳方法是什么?现在我正在做类似的事情:
(defun example-float-overflow-no-error (x)
(if (> (* x x) 1.0e20)
x
(example-float-overflow-no-error (* x x))))
(example-float-overflow 4.4)
=> 1.973525870240772e10
注意:我对结果并不感兴趣,但我的其余代码依赖于它在溢出之前运行多次。
答案 0 :(得分:1)
Barmar suggested在溢出发生后立即处理浮点溢出条件。这比检测它即将发生的时间稍微多一点,但它可能是最容易做到的事情。例如,这是一个添加功能,添加就像 + 一样,除非出现问题,您可以使用 use-value 重启提供不同的价值:
(defun add (&rest numbers)
"Add numbers with +, but with a USE-VALUE restart
available in case of an overflow (or other condition)."
(restart-case (reduce '+ numbers)
(use-value (value &optional condition) value)))
然后,如果对添加的调用失败,您可以建立使用价值重新启动,以便提供值:
;; Attempt to some arithmetic, but with a handler bound that
;; will return 42 if an floating point-overflow occurs.
(handler-bind ((floating-point-overflow
(lambda (condition)
(use-value 42 condition))))
(+ 5 (add most-positive-double-float most-positive-double-float)))
;; |----------- this ends up evaluating to 42 ---------------|
;;|------------- and 42 + 5 is 47 --------------------------------|
;=> 47