專欄簡(jiǎn)介
本專欄是優(yōu)質(zhì)Rust技術(shù)專欄,推薦精通一門技術(shù)棧的蟹友,不建議完全無計(jì)算機(jī)基礎(chǔ)的同學(xué)
感謝Rust圣經(jīng)開源社區(qū)的同學(xué),為后來者提供了非常優(yōu)秀的Rust學(xué)習(xí)資源
本文使用:
- 操作系統(tǒng)macOS Sonoma 14 / Apple M1
- 編譯器:Rustc & Cargo
感謝一路相伴的朋友們,感謝你們的支持 ^?_?^
Rust教程:How to Rust-基本類型
目錄
專欄簡(jiǎn)介
更新記錄
前言
整型
整型溢出
浮點(diǎn)型
NaN
?使用As進(jìn)行類型轉(zhuǎn)換
結(jié)語
本文參考文獻(xiàn)
更新記錄
2024.3.24 發(fā)布文章
前言
Rust中的整型怎么寫?整型溢出會(huì)怎么樣?浮點(diǎn)型呢?NaN是什么?如何進(jìn)行類型轉(zhuǎn)換?
整型
Rust的類型系統(tǒng)與其他編程語言有許多相似之處,但Rust對(duì)類型的處理有其獨(dú)特之處。在Rust中,整數(shù)類型的符號(hào)大小直接體現(xiàn)在類型名稱中,這有助于清晰地表達(dá)每個(gè)類型的取值范圍。
Rust的整數(shù)類型如下:
長(zhǎng)度 | 有符號(hào)類型 | 無符號(hào)類型 |
---|---|---|
8位 | i8 | u8 |
16位 | i16 | u16 |
32位 | i32 | u32 |
64位 | i64 | u64 |
128位 | i128 | u128 |
視架構(gòu) | isize | usize |
類型定義的形式統(tǒng)一為:有無符號(hào) + 大?。ㄎ粩?shù))。無符號(hào)數(shù)表示數(shù)字只能取正數(shù)和0,而有符號(hào)則表示數(shù)字可以取正數(shù)、負(fù)數(shù)以及0。就像我們?cè)诩埳蠈憯?shù)字一樣,當(dāng)需要強(qiáng)調(diào)符號(hào)時(shí),數(shù)字前面可以帶上正號(hào)或負(fù)號(hào);然而,當(dāng)很明顯確定數(shù)字為正數(shù)時(shí),就不需要加上正號(hào)了。有符號(hào)數(shù)字在Rust中是以補(bǔ)碼形式存儲(chǔ)的。
在Rust編程語言中,isize
和usize
是兩個(gè)與平臺(tái)相關(guān)的整數(shù)類型。它們的大小取決于目標(biāo)機(jī)器的指針大小。isize
是一個(gè)有符號(hào)整數(shù)類型,其大小與機(jī)器的字大小相同。在32位系統(tǒng)上,isize
通常是32位;在64位系統(tǒng)上,isize
通常是64位。usize
則是相應(yīng)的無符號(hào)版本。
整型溢出
關(guān)于整型溢出,Rust有一些特別的規(guī)則。當(dāng)在debug模式編譯時(shí),Rust會(huì)檢查整型溢出,并在發(fā)現(xiàn)溢出時(shí)使程序panic(即崩潰)。然而,在release模式下編譯時(shí),Rust不檢測(cè)溢出,而是按照補(bǔ)碼循環(huán)溢出的規(guī)則處理。這意味著大于該類型最大值的數(shù)值會(huì)被轉(zhuǎn)換成該類型能夠支持的對(duì)應(yīng)的最小值。例如,在u8
類型中,256會(huì)變成0,257會(huì)變成1,以此類推。
為了顯式處理可能的溢出,Rust標(biāo)準(zhǔn)庫為原始數(shù)字類型提供了一系列方法:
- 使用
wrapping_*
方法在所有模式下都按照補(bǔ)碼循環(huán)溢出規(guī)則處理,例如wrapping_add
。 - 如果使用
checked_*
方法時(shí)發(fā)生溢出,則返回None
值。 - 使用
overflowing_*
方法返回該值和一個(gè)指示是否存在溢出的布爾值。 - 使用
saturating_*
方法,可以限定計(jì)算后的結(jié)果不超過目標(biāo)類型的最大值或不低于最小值。
例如:
let result1 = (250_u8).wrapping_add(10); // 結(jié)果是 4
let result2 = (120_i8).wrapping_add(10); // 結(jié)果是 -126
let result3 = (300_u16).wrapping_mul(800); // 結(jié)果是 43392
let result4 = (-100_i8).wrapping_sub(100); // 結(jié)果是 56
在這些例子中,wrapping_*
方法用于在溢出時(shí)按照補(bǔ)碼循環(huán)溢出的規(guī)則進(jìn)行處理,而不是使程序崩潰。然而,需要注意的是,依賴這種默認(rèn)行為的代碼通常被認(rèn)為是錯(cuò)誤的,因?yàn)樗赡軐?dǎo)致程序中的邏輯錯(cuò)誤或數(shù)據(jù)損壞。在編寫涉及整數(shù)運(yùn)算的代碼時(shí),應(yīng)該仔細(xì)考慮如何處理可能的溢出情況,并使用適當(dāng)?shù)姆椒▉頇z查或處理它們
浮點(diǎn)型
浮點(diǎn)類型數(shù)字是帶有小數(shù)點(diǎn)的數(shù)值,在Rust中,主要有兩種浮點(diǎn)類型:f32
和f64
,分別對(duì)應(yīng)32位和64位大小的浮點(diǎn)數(shù)。默認(rèn)情況下,Rust使用f64
作為浮點(diǎn)類型,因?yàn)樵诂F(xiàn)代CPU上,盡管f32
和f64
的速度相差無幾,但f64
提供了更高的精度。
let variable_float = 2.0;
let variable_f32: f32 = 3.0;
變量variable_float
的類型是默認(rèn)的f64
,而變量variable_f32
的類型則是顯式聲明的f32
。當(dāng)然,你也可以顯式聲明f64
類型的變量,例如:
let variable_f64: f64 = 4.0;
使用浮點(diǎn)數(shù)時(shí),如果不謹(jǐn)慎,可能會(huì)帶來一些潛在的危險(xiǎn)。這主要有兩個(gè)原因:
首先,浮點(diǎn)數(shù)通常是用來近似表達(dá)你想要的數(shù)值。請(qǐng)注意,這里的“近似表達(dá)”是因?yàn)楦↑c(diǎn)數(shù)類型是基于二進(jìn)制實(shí)現(xiàn)的,而我們通常使用的數(shù)字則是基于十進(jìn)制的。例如,數(shù)值0.1
在二進(jìn)制中無法精確表示,這導(dǎo)致了一定的歧義。盡管浮點(diǎn)數(shù)能夠代表真實(shí)的數(shù)值,但由于其底層格式的限制,它通常受限于定長(zhǎng)的浮點(diǎn)數(shù)精度。如果你需要表達(dá)完全精確的真實(shí)數(shù)字,則需要使用具有無限精度的數(shù)學(xué)庫。
其次,浮點(diǎn)數(shù)在某些特性上是反直覺的。雖然可以使用>
、>=
等運(yùn)算符對(duì)浮點(diǎn)數(shù)進(jìn)行比較,但在某些場(chǎng)景下,這種直覺上的比較特性可能會(huì)導(dǎo)致錯(cuò)誤。f32
和f64
上的比較運(yùn)算實(shí)現(xiàn)了std::cmp::PartialEq
特性,但并沒有實(shí)現(xiàn)std::cmp::Eq
特性,而后者在其他數(shù)值類型上都有定義。
來看個(gè)例子
fn main()
{
assert_eq!(0.1 + 0.2, 0.3); // 這行代碼會(huì)觸發(fā) panic,因?yàn)槎M(jìn)制精度問題導(dǎo)致 0.1 + 0.2 不嚴(yán)格等于 0.3
}
上述代碼中,第三行是一個(gè)斷言,斷言0.1 + 0.2
的結(jié)果就是0.3
。然而,由于二進(jìn)制精度的問題,0.1 + 0.2
并不嚴(yán)格等于0.3
,它們之間可能存在小數(shù)點(diǎn)后某位的誤差,這與大多數(shù)編程語言中的浮點(diǎn)數(shù)行為是一致的。
NaN
對(duì)于數(shù)學(xué)上未定義的結(jié)果,如負(fù)數(shù)開平方根,Rust的浮點(diǎn)數(shù)類型會(huì)使用NaN(Not a Number)來處理這些情況。任何與NaN進(jìn)行交互的操作都會(huì)返回NaN,并且NaN不能用于比較(如斷言),這會(huì)導(dǎo)致程序崩潰。
例如,以下代碼會(huì)產(chǎn)生NaN:
fn main()
{
let variable = (-1.1_f64).sqrt();
}
為了避免程序因NaN而崩潰,我們可以使用一些方法來檢查數(shù)值是否為NaN,例如使用.is_nan()
方法:
fn main()
{
let variable = (-1.1_f64).sqrt();
if variable.is_nan()
{
println!("NaN")
}
}
使用.is_nan()
可以幫助我們安全地處理可能產(chǎn)生NaN的浮點(diǎn)數(shù)運(yùn)算。?
?使用As進(jìn)行類型轉(zhuǎn)換
在Rust中,as
關(guān)鍵字用于在原始類型(如i64
、f64
、u64
、char
等)之間進(jìn)行類型轉(zhuǎn)換。然而,需要注意的是,as
關(guān)鍵字并不適用于復(fù)合類型,比如String
或其他用戶定義的類型。對(duì)于復(fù)合類型的轉(zhuǎn)換,通常需要使用其他方法或函數(shù)。
例如,如果你有一個(gè)i32
類型的變量,并希望將其轉(zhuǎn)換為f64
類型的浮點(diǎn)數(shù),你可以使用as
關(guān)鍵字來實(shí)現(xiàn)這一轉(zhuǎn)換:
let num_i32: i32 = 42;
let num_f64: f64 = num_i32 as f64;
但是,as
關(guān)鍵字的使用是有限制的,它只能在那些具有明確定義轉(zhuǎn)換規(guī)則的類型之間起作用。如果嘗試在不兼容的類型之間進(jìn)行轉(zhuǎn)換,Rust編譯器會(huì)報(bào)錯(cuò)。例如,下面的代碼嘗試將一個(gè)String
轉(zhuǎn)換為i32
,這是不允許的,因?yàn)?code>String和i32
之間沒有直接的轉(zhuǎn)換關(guān)系:
let str_num = "123".to_string();
let num_i32: i32 = str_num as i32; // 這行會(huì)報(bào)錯(cuò),因?yàn)?String 不能直接轉(zhuǎn)換為 i32
在上面的代碼中,嘗試使用as
來轉(zhuǎn)換str_num
變量會(huì)導(dǎo)致編譯錯(cuò)誤,因?yàn)?code>String類型不能直接用as
關(guān)鍵字轉(zhuǎn)換為i32
類型。如果需要將字符串轉(zhuǎn)換為整數(shù),你需要使用其他方法,比如parse
方法:
let str_num = "123";
let num_i32: i32 = str_num.parse().unwrap(); // 使用 parse 方法來將字符串轉(zhuǎn)換為整數(shù)
在上面的代碼中,我們使用了parse()
方法,該方法嘗試將字符串解析為相應(yīng)的數(shù)值類型,并返回一個(gè)Result
枚舉,表示解析操作是否成功。使用unwrap()
方法可以獲取解析結(jié)果,但如果解析失?。ū热缱址皇怯行У臄?shù)字表示),則會(huì)觸發(fā)panic。在實(shí)際應(yīng)用中,通常需要對(duì)parse()
的返回值進(jìn)行更健壯的錯(cuò)誤處理。
因此,在使用as
進(jìn)行類型轉(zhuǎn)換時(shí),需要確保轉(zhuǎn)換的類型之間具有明確定義的轉(zhuǎn)換關(guān)系,并且不適用于復(fù)合類型或沒有直接轉(zhuǎn)換關(guān)系的類型。對(duì)于更復(fù)雜的類型轉(zhuǎn)換需求,需要利用Rust提供的相應(yīng)函數(shù)或方法。
結(jié)語
如果本文有任何問題歡迎在評(píng)論去指出,如果喜歡這篇文章,希望能點(diǎn)贊評(píng)論關(guān)注
如果你們身邊有像你提起過這個(gè)領(lǐng)域的,或者希望可以和ta一起進(jìn)步的,把這篇文章分享給ta吧
本文共3646字
本文參考文獻(xiàn)
Rust圣經(jīng)
文心一言?
菜鳥求助,使用 isize 或 usize 作為索引類型更加靈活 - Rust語言中文社區(qū)
在 Rust 中處理整數(shù)溢出文章來源:http://www.zghlxwxcb.cn/news/detail-848512.html
https://www.cnblogs.com/ywxt/p/11801778.html文章來源地址http://www.zghlxwxcb.cn/news/detail-848512.html
到了這里,關(guān)于Rust教程:How to Rust-基本類型的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!