一起學Rust-實戰leetcode(五)
- 2019 年 10 月 7 日
- 筆記
微信關注公眾號 [可回收BUG]
給出一個 32 位的有符號整數,你需要將這個整數中每位上的數字進行反轉。
示例 1:
輸入: 123 輸出: 321
示例 2:
輸入: -123 輸出: -321
示例 3:
輸入: 120 輸出: 21
注意:
假設我們的環境只能存儲得下 32 位的有符號整數,則其數值範圍為 [−2^31, 2^31 − 1]。請根據這個假設,如果反轉後整數溢出那麼就返回 0。
來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/reverse-integer
這是來源於leetcode的一道題 「整數反轉」,我們使用Rust來實現。
本次實戰目的:
對 Option<T> 的取值函數的複習,與數字溢出的情況處理。
簡單分析:
題目需要將數字反轉過來,並保留當前的符號,數字類型是 i32 ,範圍是[2147483647,-2147483648]。
對於數字的每一位可以通過不斷對數字以10為除數取余和對剩下的數字被10整除的商再次進行取余,便可以依次取取出各位數字。
例如:
x = 123,
x % 10 = 3,x = floor(x / 10) = 12,
x % 10 = 2,x = floor(x/10) = 1,
x % 10 = 1。x = floor(x/10) = 0,停止。
分別依次得到3,2,1。
剛好第一個就可以獲得目標結果數字的第一個,那麼每次將其當前總結果乘10後與計算結果相加:
ret = 0
x % 10 = 3,ret = ret * 10 + 3 = 3
x % 10 = 2,ret = ret * 10 + 2 = 30 + 2
x % 10 = 1,ret = ret * 10 + 1 = 320 + 1
下面看一下程式碼:
fn reverse(x: i32) -> i32 { let mut x = x; let mut result:Option<i32> = Some(0); loop { if x == 0 { break; } let tmp_num = x % 10; x = x / 10; result = result.unwrap().checked_mul(10); if result.is_none() { return 0_i32; } result = tmp_num.checked_add(result.unwrap()); if result.is_none() { return 0_i32; } } result.unwrap() }
解釋:
checked_mul(y) 乘法,可以由數字或者數字變數直接調用,需要明確數字類型,此函數結果會返回Option<T>類型,溢出範圍則返回None。
checked_add(y) 加法,溢出後返回None。
unwrap() 獲取枚舉內的值,會獲取枚舉變數的所有權。
注意:
用IDE書寫程式碼時,checked_mul 和 checked_add 並沒有提示,我們看一下 i32 的方法實現:
#[lang = "i32"] impl i32 { int_impl! { i32, i32, u32, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } }
i32 定義的方法內部是通過 int_impl! 宏展開的方法。int_impl! 宏內對checked_mul 定義了文檔、文檔內測試和方法體。
doc_comment! { concat!("Checked integer multiplication. Computes `self * rhs`, returning `None` if overflow occurred. # Examples Basic usage: ``` ", $Feature, "assert_eq!(", stringify!($SelfT), "::max_value().checked_mul(1), Some(", stringify!($SelfT), "::max_value())); assert_eq!(", stringify!($SelfT), "::max_value().checked_mul(2), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "this returns the result of the operation, without modifying the original"] #[inline] pub fn checked_mul(self, rhs: Self) -> Option<Self> { let (a, b) = self.overflowing_mul(rhs); if b {None} else {Some(a)} } }
文件:share/rust/rust_src/libcore/num/mod.rs
完