在 Common Lisp 中测试一个不可知的浮点错误=

如何解决在 Common Lisp 中测试一个不可知的浮点错误=

为了对涉及大量浮点运算的系统进行一些测试,我定义了浮点运算误差的偏差范围,因此如果两个浮点数之间的差异在偏差范围内,则它们被认为在数学上是相等的:>

;;; Floating Error Agnostic =
;;; F2 is = to F1 within the deviation range +-DEV

(defparameter *flerag-devi* .0005
  "Allowed deviation range,within which two floats 
should be considered as mathematically equal.")

(defun flerag= (f1 f2 &optional (devi *flerag-devi*))
  ""
  (<= (abs (- f1 f2)) devi))

现在,当我通过比较浮点数和随机分数添加来测试函数时,响应是(至少对于我对函数的测试)是正面的,例如:

(loop repeat 100000000
      with f = 1.0
      always (flerag= f (+ f (random *flerag-devi*)))) ;T

当我从原始浮点数中减去一个随机分数时也是这种情况,例如:


(loop repeat 100000000
      with f = 19.0
      always (flerag= f (- f (random *flerag-devi*)))) ;T

(loop repeat 100000000
      with f = 3
      always (flerag= f (- f (random *flerag-devi*)))) ;T

但是,当我将原始浮点数设置为 1.0(或 1)时:

(loop repeat 100000000
      with f = 1.0
      always (flerag= f (- f (random *flerag-devi*)))) ;NIL

它总是返回 NIL,这在我看来更奇怪,因为它在评估后立即返回 NIL(在其他情况下,计算 100000000 次需要几秒钟)。到目前为止,这仅发生在 f = 1.0 上,没有其他数字发生,无论对它们的分数进行加法 还是减法。任何人都可以在他/她的 Lisp 上重现这种行为吗?任何解释和帮助将不胜感激。

更新 当我使用双浮点数 1,即 1d0 或通过执行以下操作时,f = 1.0 的情况也适用于其他情况:

(setf *read-default-float-format* 'double-float)

解决方法

欢迎来到浮点运算:一个可怕的陷阱等待着即使是谨慎的人,而粗心的人会立即被仇恨吞噬。请参阅 this,您可以获得 here 的 PDF 副本(此副本可能合法,但像 Oracle 这样的人也有免费提供的版本),而且这篇论文不能免费提供,这有点愚蠢给大家。

这里发生的事情是,假设单个浮点数,在某个时刻 (random 0.0005) 产生一个数字 r(例如 4.9999706E-4),它足够接近 0.0005 (- 1.0 r)0.9995。但是 (- 1.0 0.9995)0.0005 更大:特别是对于单人浮点数(也许对于双人也是如此,但绝对是对于单人),存在单人浮点数 r 使得

(and (< r 0.0005)
     (> (- 1.0 (- 1.0 r)) 0.0005)))

可能有可能系统地枚举这样的单个浮点数,但我太懒了。

“足够接近”的定义还取决于您所测量的语义是什么。如果您正在比较物体的直径,您可能不希望出现 x 与 y 都“足够接近”且 x >> y 的情况:1.5E-18 在 {{1} 的 0.0005 之内},但是如果你测量的是质子的半径,你会相差十个数量级,这是一个不小的误差。

像下面这样的定义(这是从前一个有问题的定义修改而来)可能适用于此。

1.5E-8

但是,如果您以摄氏度为单位测量温度,那么您不希望事情在接近零时变得特别挑剔(除非您非常关心冰的形成,在这种情况下您可能会这样做)。

但是我不是浮点专家:我只知道这完全是一场噩梦。


作为一个无关的说明:您的 (defun close-enough-p (f1 f2 &optional (epsilon 0.0005)) (declare (type real f1 f2 epsilon)) (let ((delta (* (abs f1) epsilon))) (<= (- f1 delta) f2 (+ f1 delta)))) 语法不合法。 loop 需要在 with 或其他迭代构造之前。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res