2 回答

TA貢獻(xiàn)1772條經(jīng)驗(yàn) 獲得超5個(gè)贊
這里的問(wèn)題是常量和浮點(diǎn)數(shù)的表示。
常量以任意精度表示。浮點(diǎn)數(shù)使用IEEE 754標(biāo)準(zhǔn)表示。
規(guī)格:常數(shù):
數(shù)字常量表示任意精度的值并且不會(huì)溢出。
規(guī)格:數(shù)字類型:
float64 the set of all IEEE-754 64-bit floating-point numbers
在 IEEE 754 中,使用 64 位(float64在 Go 中)的雙精度53 位用于存儲(chǔ)數(shù)字。這意味著可以表示的最大位數(shù)(max number)是其中的位數(shù)2<<52(1位用于符號(hào)):
2<<52 : 9007199254740992
Your constant: 6161047830682206209
準(zhǔn)確地說(shuō)是 15.95 位(16 位,但不是您可以用 16 位描述的所有值,最多只能是9007199254740992)。
您嘗試放入類型變量的整數(shù)常量float64根本不適合 52 位,因此必須四舍五入并且數(shù)字(或位)將被截?cái)啵▉G失)。
您可以通過(guò)打印原始n float64號(hào)碼來(lái)驗(yàn)證這一點(diǎn):
var n float64 = 6161047830682206209
fmt.Printf("%f\n", n)
fmt.Printf("%d\n", uint64(n))
輸出:
6161047830682206208.000000
6161047830682206208
問(wèn)題不在于轉(zhuǎn)換,問(wèn)題在于float64您嘗試轉(zhuǎn)換的值已經(jīng)不等于您嘗試分配給它的常量。
只是出于好奇:
嘗試使用更大的數(shù)字:與第一個(gè)常量相比+500:
n = 6161047830682206709 // +500 compared to first!
fmt.Printf("%f\n", n2)
fmt.Printf("%d\n", uint64(n2))
輸出仍然相同(最后一位數(shù)字/位被截?cái)?,包?500?。?/p>
6161047830682206208.000000
6161047830682206208
嘗試一個(gè)較小的數(shù)字,其數(shù)字可以使用 52 位(小于 ~16 位)精確表示:
n = 7830682206209
fmt.Printf("%f\n", n)
fmt.Printf("%d\n", uint64(n))
輸出:
7830682206209.000000
7830682206209
在Go Playground上試一試。

TA貢獻(xiàn)1876條經(jīng)驗(yàn) 獲得超5個(gè)贊
問(wèn)題不在于轉(zhuǎn)換,而在于數(shù)字太大,無(wú)法完全存儲(chǔ)為float64
. 分配給n
導(dǎo)致一些意義的損失。
如果你仔細(xì)想想,你的數(shù)字(大約 6e18)非常接近最大的uint64
(2^64-1 或大約 18e18)。Auint64
使用全部 64 位來(lái)存儲(chǔ)整數(shù),但float64
必須使用其 64 位中的一部分來(lái)存儲(chǔ)指數(shù),因此它可以使用更少的位來(lái)記住尾數(shù)。
總之,如果您將一個(gè)uint64
大于 10^15的(或整數(shù)常量)分配給 afloat64
并返回給 a,uint64
您將獲得一個(gè)接近但可能不完全相同的值。
[BTW Icza 的回答很好而且正確。我希望這個(gè)答案是簡(jiǎn)單的總結(jié)。]
- 2 回答
- 0 關(guān)注
- 386 瀏覽
添加回答
舉報(bào)