Python 3.x TensorFlow添加大数
在我的模型中,我可以将一些小的数字与一些大的数字相加。但这会产生一个不正确的值。以下是一个简化的示例:Python 3.x TensorFlow添加大数,python-3.x,tensorflow2.0,Python 3.x,Tensorflow2.0,在我的模型中,我可以将一些小的数字与一些大的数字相加。但这会产生一个不正确的值。以下是一个简化的示例: import tensorflow as tf a = tf.Variable(-1.55786165e+14 ,dtype=np.float32) b = tf.Variable(-112522840.,dtype=np.float32) c = tf.Variable(-34. ,dtype=np.float32) a+b+c 这将给出,其中正确答案应该是-15578627752287
import tensorflow as tf
a = tf.Variable(-1.55786165e+14 ,dtype=np.float32)
b = tf.Variable(-112522840.,dtype=np.float32)
c = tf.Variable(-34. ,dtype=np.float32)
a+b+c
这将给出
,其中正确答案应该是-155786277522874
如何更正此问题?使用
numpy
可以直接观察到相同的行为。但是,这仅在使用dtype=np.float32
而不是dtype=np.float64
时出现。将您的dtype
更改为np.float64
,以更正此问题
为了理解原因,您必须了解浮点数是如何存储在内存中的。让我们考虑“代码> A <代码>,以单精度和双精度表示:
将numpy导入为np
a=-1.55786165e+14
a_single=np.array([a],dtype=np.float32)
a_double=np.array([a],dtype=np.float64)
单[0],双[0],a
#上面的行打印:
# (-155786160000000.0, -155786165000000.0, -155786165000000.0)
如您所见,a
在使用单精度时被截断。但为什么呢
abs(a)
的以2为底的对数介于47和48之间。因此,a
可以写成-1*2^47*1.x
。表示浮点数时,必须对指数(48)和分数(x)进行编码
在我们的例子中,.x
大约等于:
-a/pow(2,47)-1
这等于0.1069272787267437
。现在,我们要把这个数写成2的负幂和,从-1开始。这意味着如果我们使用N
位来表示它,我们将在内存中存储0.1069272787267437*pow(2,N)
的整数部分
在单精度中,我们使用N=23
位来表示这个数字。由于0.1069272787267437*pow(2,23)
的整数部分为896971,其二进制扩展为11011010111111001011
,长度为20位,因此存储在内存中的数字为00010101111111001011
但是,当使用双精度时,存储在内存中的数字是00010110101111001011000000100100101110000000000
。请注意,大量尾随零可能表示存储了a
的精确值(因为我们不需要更高的精度来表示它),这里就是这种情况
这就是说,这解释了为什么a
在表示为单精度浮点时被截断。将b
添加到a
时,同样的推理也适用。由于结果浮点的指数将是47
,这意味着在单精度中可以声明的最小可能精度是2^47*2^-23=2^24
,而在双精度中可以声明的最小可能精度是2^47*2^-52=2^-5
。由于您使用的是整数,这就解释了为什么您会得到双精度的精确结果和单精度的不正确结果