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
。由于您使用的是整数,这就解释了为什么您会得到双精度的精确结果和单精度的不正确结果