整形与浮点型
01. 整形
Go 語(yǔ)言中,整數(shù)類型可以再細(xì)分成10個(gè)類型,
int 和 uint 的區(qū)別就在于一個(gè)u,有u說(shuō)明是無(wú)符號(hào),沒(méi)有u代表有符號(hào)。
解釋這個(gè)符號(hào)的區(qū)別
以int8和uint8舉例,8 代表 8個(gè)bit,能表示的數(shù)值個(gè)數(shù)有 2^8 = 256。
uint8 是無(wú)符號(hào),能表示的都是正數(shù),0-255,剛好256個(gè)數(shù)。
int8 是有符號(hào),既可以正數(shù),也可以負(fù)數(shù),那怎么辦?對(duì)半分唄,-128-127,也剛好 256個(gè)數(shù)。
int8 int16 int32 int64 這幾個(gè)類型的最后都有一個(gè)數(shù)值,這表明了它們能表示的數(shù)值個(gè)數(shù)是固定的。
而 int 沒(méi)有并沒(méi)有指定它的位數(shù),說(shuō)明它的大小,是可以變化的,那根據(jù)什么變化呢?
當(dāng)你在32位的系統(tǒng)下,int 和 uint 都占用 4個(gè)字節(jié),也就是32位。
若你在64位的系統(tǒng)下,int 和 uint 都占用 8個(gè)字節(jié),也就是64位。
出于這個(gè)原因,在某些場(chǎng)景下,你應(yīng)當(dāng)避免使用 int 和 uint ,而使用更加精確的 int32 和 int64,比如在二進(jìn)制傳輸、讀寫文件的結(jié)構(gòu)描述(為了保持文件的結(jié)構(gòu)不會(huì)受到不同編譯目標(biāo)平臺(tái)字節(jié)長(zhǎng)度的影響)
不同進(jìn)制的表示方法
出于習(xí)慣,在初始化數(shù)據(jù)類型為整形的變量時(shí),我們會(huì)使用10進(jìn)制的表示法,因?yàn)樗钪庇^,比如這樣,表示整數(shù)10.
var num int = 10
不過(guò),你要清楚,你一樣可以使用其他進(jìn)制來(lái)表示一個(gè)整數(shù),這里以比較常用的2進(jìn)制、8進(jìn)制和16進(jìn)制舉例。
2進(jìn)制:以0b或0B為前綴
var num01 int = 0b1100
8進(jìn)制:以0o或者0O為前綴
var num02 int = 0o14
16進(jìn)制:以0x為前綴
var num03 int = 0xC
下面用一段代碼分別使用二進(jìn)制、8進(jìn)制、16進(jìn)制來(lái)表示 10 進(jìn)制的數(shù)值:12
package main
import (
"fmt"
)
func main() {
var num01 int = 0b1100
var num02 int = 0o14
var num03 int = 0xC
fmt.Printf("2進(jìn)制數(shù) %b 表示的是: %d
", num01, num01)
fmt.Printf("8進(jìn)制數(shù) %o 表示的是: %d
", num02, num02)
fmt.Printf("16進(jìn)制數(shù) %X 表示的是: %d
", num03, num03)
}
輸出如下
2進(jìn)制數(shù) 1100 表示的是: 12
8進(jìn)制數(shù) 14 表示的是: 12
16進(jìn)制數(shù) C 表示的是: 12
以上代碼用過(guò)了 fmt 包的格式化功能,你可以參考這里去看上面的代碼
%b 表示為二進(jìn)制 %c 該值對(duì)應(yīng)的unicode碼值 %d 表示為十進(jìn)制 %o 表示為八進(jìn)制 %q 該值對(duì)應(yīng)的單引號(hào)括起來(lái)的go語(yǔ)法字符字面值,必要時(shí)會(huì)采用安全的轉(zhuǎn)義表示 %x 表示為十六進(jìn)制,使用a-f %X 表示為十六進(jìn)制,使用A-F %U 表示為Unicode格式:U+1234,等價(jià)于"U+%04X"
02. 浮點(diǎn)型
浮點(diǎn)數(shù)類型的值一般由整數(shù)部分、小數(shù)點(diǎn)“.”和小數(shù)部分組成。
其中,整數(shù)部分和小數(shù)部分均由10進(jìn)制表示法表示。不過(guò)還有另一種表示方法。那就是在其中加入指數(shù)部分。指數(shù)部分由“E”或“e”以及一個(gè)帶正負(fù)號(hào)的10進(jìn)制數(shù)組成。比如,3.7E-2表示浮點(diǎn)數(shù)0.037。又比如,3.7E+1表示浮點(diǎn)數(shù)37。
有時(shí)候,浮點(diǎn)數(shù)類型值的表示也可以被簡(jiǎn)化。比如,37.0可以被簡(jiǎn)化為37。又比如,0.037可以被簡(jiǎn)化為.037。
有一點(diǎn)需要注意,在Go語(yǔ)言里,浮點(diǎn)數(shù)的相關(guān)部分只能由10進(jìn)制表示法表示,而不能由8進(jìn)制表示法或16進(jìn)制表示法表示。比如,03.7表示的一定是浮點(diǎn)數(shù)3.7。
float32 和 float64
Go語(yǔ)言中提供了兩種精度的浮點(diǎn)數(shù) float32 和 float64。
float32,也即我們常說(shuō)的單精度,存儲(chǔ)占用4個(gè)字節(jié),也即4*8=32位,其中1位用來(lái)符號(hào),8位用來(lái)指數(shù),剩下的23位表示尾數(shù)
float64,也即我們熟悉的雙精度,存儲(chǔ)占用8個(gè)字節(jié),也即8*8=64位,其中1位用來(lái)符號(hào),11位用來(lái)指數(shù),剩下的52位表示尾數(shù)
那么精度是什么意思?有效位有多少位?
精度主要取決于尾數(shù)部分的位數(shù)。
對(duì)于 float32(單精度)來(lái)說(shuō),表示尾數(shù)的為23位,除去全部為0的情況以外,最小為2^-23,約等于1.19*10^-7,所以float小數(shù)部分只能精確到后面6位,加上小數(shù)點(diǎn)前的一位,即有效數(shù)字為7位。
同理 float64(單精度)的尾數(shù)部分為 52位,最小為2^-52,約為2.22*10^-16,所以精確到小數(shù)點(diǎn)后15位,加上小數(shù)點(diǎn)前的一位,有效位數(shù)為16位。
通過(guò)以上,可以總結(jié)出以下幾點(diǎn):
1. float32 和 float64 可以表示的數(shù)值很多
浮點(diǎn)數(shù)類型的取值范圍可以從很微小到很巨大。浮點(diǎn)數(shù)取值范圍的極限值可以在 math 包中找到:
常量 math.MaxFloat32 表示 float32 能取到的最大數(shù)值,大約是 3.4e38;
常量 math.MaxFloat64 表示 float64 能取到的最大數(shù)值,大約是 1.8e308;
float32 和 float64 能表示的最小值分別為 1.4e-45 和 4.9e-324。
2. 數(shù)值很大但精度有限
人家雖然能表示的數(shù)值很大,但精度位卻沒(méi)有那么大。
float32的精度只能提供大約6個(gè)十進(jìn)制數(shù)(表示后科學(xué)計(jì)數(shù)法后,小數(shù)點(diǎn)后6位)的精度
float64的精度能提供大約15個(gè)十進(jìn)制數(shù)(表示后科學(xué)計(jì)數(shù)法后,小數(shù)點(diǎn)后15位)的精度
這里的精度是什么意思呢?
比如 10000018這個(gè)數(shù),用 float32 的類型來(lái)表示的話,由于其有效位是7位,將10000018 表示成科學(xué)計(jì)數(shù)法,就是 1.0000018 * 10^7,能精確到小數(shù)點(diǎn)后面6位。
此時(shí)用科學(xué)計(jì)數(shù)法表示后,小數(shù)點(diǎn)后有7位,剛剛滿足我們的精度要求,意思是什么呢?此時(shí)你對(duì)這個(gè)數(shù)進(jìn)行+1或者-1等數(shù)學(xué)運(yùn)算,都能保證計(jì)算結(jié)果是精確的
import "fmt"
var myfloat float32 = 10000018
func main() {
fmt.Println("myfloat: ", myfloat)
fmt.Println("myfloat: ", myfloat+1)
}
輸出如下
myfloat: 1.0000018e+07
myfloat: 1.0000019e+07
上面舉了一個(gè)剛好滿足精度要求數(shù)據(jù)的臨界情況,為了做對(duì)比,下面也舉一個(gè)剛好不滿足精度要求的例子。只要給這個(gè)數(shù)值多加一位數(shù)就行了。
換成 100000187,同樣使用 float32類型,表示成科學(xué)計(jì)數(shù)法,由于精度有限,表示的時(shí)候小數(shù)點(diǎn)后面7位是準(zhǔn)確的,但若是對(duì)其進(jìn)行數(shù)學(xué)運(yùn)算,由于第八位無(wú)法表示,所以運(yùn)算后第七位的值,就會(huì)變得不精確。
這里我們寫個(gè)代碼來(lái)驗(yàn)證一下,按照我們的理解下面 myfloat01 = 100000182 ,對(duì)其+5操作后,應(yīng)該等于 myfloat02 = 100000187,
import "fmt"
var myfloat01 float32 = 100000182
var myfloat02 float32 = 100000187
func main() {
fmt.Println("myfloat: ", myfloat01)
fmt.Println("myfloat: ", myfloat01+5)
fmt.Println(myfloat02 == myfloat01+5)
}
但是由于其類型是 float32,精度不足,導(dǎo)致最后比較的結(jié)果是不相等(從小數(shù)點(diǎn)后第七位開(kāi)始不精確)
myfloat: 1.00000184e+08 myfloat: 1.0000019e+08 false
由于精度的問(wèn)題,就會(huì)出現(xiàn)這種很怪異的現(xiàn)象,myfloat == myfloat +1會(huì)返回true。
總結(jié)
- 上一篇: ftp服务及配置
- 下一篇: windows远程工具RDO和RDC使用