gpt4 book ai didi

python - 从 np.float64 转换为 np.float32 完全改变了一些数字的值

转载 作者:行者123 更新时间:2023-12-05 03:16:46 36 4
gpt4 key购买 nike

我有一个 dtype=float64 的 numpy 数组,当试图将其类型转换为 float 32 时,一些值完全改变了。例如,我有以下数组:

`test_64 = np.array([20110927.00000,20110928.00000,20110929.00000,20110930.00000,20111003.00000,20111004.00000,20111005.00000,20111006.00000,20111007.00000,20111010.00000,20111011.00000,20111012.00000,20111013.00000,20111014.00000,20111017.00000,20111018.00000,20111019.00000,20111020.00000,20111021.00000,20111024.00000 ,20111025.00000,20111026.00000,20111027.00000,20111028.00000,20111031.00000,20111101.00000,20111102.00000,20111103.00000,20111104.00000,20111107.00000,20111108.00000,20111109.00000,20111110.00000,20111111.00000,20111114.00000,20111115.00000,20111116.00000,20111117.00000,20111118.00000,20111121.00000,20111122.00000,20111123.00000,20111125.00000,20111128.00000,20111129.00000 ,20111130.00000,20111201.00000,20111202.00000,20111205.00000,20111206.00000,20111207.00000,20111208.00000,20111209.00000,20111212.00000,20111213.00000,20111214.00000,20111215.00000,20111216.00000,20111219.00000,20111220.00000,20111221.00000,20111222.00000,20111223.00000,20111227.00000,20111228.00000,2 0111229.00000,20111230.00000,20120103.00000,20120104.00000,20120105.00000,20120106.00000,20120109.00000,20120110.00000,20120111.00000,20120112.00000,20120113.00000,20120117.00000,20120118.00000,20120119.00000,20120120.00000,20120123.00000,20120124.00000,20120125.00000,20120126.00000,20120127.00000,20120130.00000,20120131.00000,20120201.00000,20120202.00000,20120203.00000, 20120206.00000,20120207.00000,201208.00000,20120209.00000,20120210210.00000,20120213.00000,20120214.00000,20120215.00000,000,20120216.00000,000,20120217.00000])

>>>>>>>>>>>>

test_32 = np.array(test_64, dtype=np.float32)`

这会将 20110927.00000 的值更改为 20110928.00000

甚至尝试:

np.float32(test_64[0])

将导致值从 20110927.00000 更改为 20110928.00000

使用 cupy 数组时发生同样的事情

最佳答案

嗯,是的,这就是 float32。

从最短的角度看,float32 有 24 位有效数(1 位符号,8 位指数)。总共是 33 位。但是第一个有效位没有被存储,因为它被假定为 1。

np.log2(20110927.)
# 24.2614762474699

所以,看到问题了。您将需要 25 位才能对该数字具有单位精度。既然你没有,那么从 float32 的角度来看,20110927 和 20110928 大致相同。

最长的答案,在 FP32 中编码 20110927,然后编码 20110928。

20110927 是 1.1987046599388123 × 2²⁴

所以指数是 24。即FP32格式的24+127=151

然后忘记第一个,这是隐式的(因为选择了指数,例如它以这个 1. 开头),23 个有效数位

s=1.1987046599388123  # Implicit   1
s=s%1*2 # 0.3974... →0
s=s%1*2 # 0.7948... →0
s=s%1*2 # 1.5896... →1
s=s%1*2 # 1.1793... →1
s=s%1*2 # 0.3585... →0
s=s%1*2 # 0.7171... →0
s=s%1*2 # 1.4342... →1
s=s%1*2 # 0.8684... →0
s=s%1*2 # 1.7368... →1
s=s%1*2 # 1.4736... →1
s=s%1*2 # 0.9471... →0
s=s%1*2 # 1.8943... →1
s=s%1*2 # 1.7886... →1
s=s%1*2 # 1.5771... →1
s=s%1*2 # 1.1543... →1
s=s%1*2 # 0.3086... →0
s=s%1*2 # 0.6172... →0
s=s%1*2 # 1.2344... →1
s=s%1*2 # 0.4688... →0
s=s%1*2 # 0.9375... →0
s=s%1*2 # 1.8750... →1
s=s%1*2 # 1.7500... →1
s=s%1*2 # 1.5000... →1

(s%1 是 float 的小数部分。1.51%10.51)

我是这样计算的,从 20110927/2²⁴ 开始,因为这是以 2 为底的编码。但实际上,这只是 20110927 24 个最高有效位的二进制编码。

bin(20119827)
# 1001100101101111001001111

请注意,这些是相同的位,但对于最后的 1,因为有 25 位,而我们只需要 24 位。包括隐式的 1。

并且因为下一位是 1,或者因为我的 float 算法的最后 s 是 1.5,所以它被四舍五入到下一位。所以最后,编码的是100110010110111100101000

(为了准确,我对这个四舍五入的东西进行了精确处理,以获得准确的结果。但这不是你的问题的原因。它没有四舍五入,所有会改变的是,而不是 20110927=20110928,你会有 20110927=20110926。但是无论如何,24 位不足以区分两个连续的大于 16777216 的 10 进制数。无论如何,这不是确定的事情。有时,.5 会向下舍入)

忽略第一个,并添加符号 (0) 和指数 (24+127=151 aka 1001011)

20110927.0的float32表示是01001011100110010110111100101000

对 20110928.0 执行相同的操作...您会得到完全相同的结果。

因此,在 float32 中,20110927.0 和 20110928.0(以及 20110927.5,...)是同一回事。

在没有关于如何编码 float32 的理论的情况下检查的另一种方法是

import struct
bin(struct.unpack('i', struct.pack('f', 20110927))[0])
# 0b1001011100110010110111100101000
bin(struct.unpack('i', struct.pack('f', 20110928))[0])
# 0b1001011100110010110111100101000

或者看大局

import struct
for i in range(20110901, 20110931):
print(i, bin(struct.unpack('i', struct.pack('f', i))[0]))
20110901 0b1001011100110010110111100011010
20110902 0b1001011100110010110111100011011
20110903 0b1001011100110010110111100011100
20110904 0b1001011100110010110111100011100
20110905 0b1001011100110010110111100011100
20110906 0b1001011100110010110111100011101
20110907 0b1001011100110010110111100011110
20110908 0b1001011100110010110111100011110
20110909 0b1001011100110010110111100011110
20110910 0b1001011100110010110111100011111
20110911 0b1001011100110010110111100100000
20110912 0b1001011100110010110111100100000
20110913 0b1001011100110010110111100100000
20110914 0b1001011100110010110111100100001
20110915 0b1001011100110010110111100100010
20110916 0b1001011100110010110111100100010
20110917 0b1001011100110010110111100100010
20110918 0b1001011100110010110111100100011
20110919 0b1001011100110010110111100100100
20110920 0b1001011100110010110111100100100
20110921 0b1001011100110010110111100100100
20110922 0b1001011100110010110111100100101
20110923 0b1001011100110010110111100100110
20110924 0b1001011100110010110111100100110
20110925 0b1001011100110010110111100100110
20110926 0b1001011100110010110111100100111
20110927 0b1001011100110010110111100101000
20110928 0b1001011100110010110111100101000
20110929 0b1001011100110010110111100101000
20110930 0b1001011100110010110111100101001

请注意,.5 的一半次数向上舍入,一半次数向下舍入。导致这种 3/1 模式。 20110919=20110920=20110921,20110922是唯一的,20110923=20110924=20110925,20110926是唯一的,20119727=20110928=20110929。 ...

但是,重要的一点是 float32 的可能性较小,在此范围内可能有 8 位以 10 为基数的数字。

关于python - 从 np.float64 转换为 np.float32 完全改变了一些数字的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74495636/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com