问题描述
lisp 中的表达式为:
(* (+ a b) (- a (/ 1 b)))
Java 中的等价表达式(我认为)是:
(a + b) * (a - (1/b));
但是当我向两者中输入相同的 a
和 b
float
值时,它们的计算结果不同。这是为什么?
解决方法
如果您使用相同的浮点类型(两者都是单打或双打),那么您所看到的可能是打印浮点数的行为的不同。很有可能这些数字实际上是一样的。默认的 CL 打印机(或应该)非常小心地打印足够的信息,以便浮点数可以读回并与它打印的相同。所以给定
(defun f (a b)
(* (+ a b) (- a (/ 1 b))))
然后我们可以用
测试读写一致性(defun tsrp (x)
(with-standard-io-syntax
(eql (read-from-string (write-to-string x))
x)))
现在在一个实现中(第一个例子是使用单精度第二个双精度,这是 CL 应该如何使用默认读取器设置读取这些):
> (f 1.001 1.0003)
0.0026016448
> (tsrp (f 1.001 1.0003))
t
> (f 1.001d0 1.0003d0)
0.002601509937018715D0
> (tsrp (f 1.001d0 1.0003d0))
t
在另一个:
? (f 1.001 1.0003)
0.0026016447
? (tsrp (f 1.001 1.0003))
t
? (f 1.001d0 1.0003d0)
0.002601509937018715D0
? (tsrp (f 1.001d0 1.0003d0))
t
请注意,两种实现在单精度情况下打印出不同的外观结果。但是你可以确认这两种表示是同一个单浮点数:
> (= 0.0026016448 0.0026016447)
t
和
? (= 0.0026016448 0.0026016447)
t
我不知道如何让 Java 打印一个浮点数,以便它可以像这样读回:我认为它可能是 %s
格式控件。如果这是对的,并且您确保您的浮点类型相同,那么您应该获得相同的表示,或者仅在数字上有所不同的表示实际上并不重要(您可以检查,使用与上述等效的代码).