防止浮点溢出在它们发生之前 [英] Prevent floating point overflows right before they happen

查看:45
本文介绍了防止浮点溢出在它们发生之前的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为溢出浮点的一种简便方法(我在代码中使用了双浮点数,所以我也在这里这样做):

As an easy way to overflow a floating point (I'm using double floats in my code, so I'll do so here as well):

(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并溢出.哪一个甚至是双浮标了?

Very quickly, x grows larger and larger. Pretty soon it reaches 5.295234290518905e164 and overflows. Which, is that even a double float anymore?

无论如何,在溢出之前识别点的最佳方法是什么?现在我正在做类似的事情:

Anyway, what is the best way to identify the point right before it overflows? Right now I'm doing something like:

(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

=> 1.973525870240772e10

注意:我实际上对结果并不感兴趣,但是我的其余代码依赖于它在溢出之前运行的次数.

Note: I'm not actually interested in the result, but the rest of my code depends on it to run as many times as it can before overflowing.

推荐答案

Barmar

Barmar suggested handling the floating-point-overflow condition just after the overflow occurs. This is a little bit than detecting when it is about to occur, but it's probably the easiest thing to do. For instance, here's an add function that adds just like +, except that if something goes wrong, you can use the use-value restart to provide a different 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)))

然后,您可以建立使用值重启,如果对 add 的调用失败,该重启可用于提供值:

Then you can establish use-value restarts that can be used to provide a value if a call to add fails:

;; 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

这篇关于防止浮点溢出在它们发生之前的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆