More work on parsing numbers from strings
timw4mail/rusty-numbers/pipeline/head This commit looks good Details

This commit is contained in:
Timothy Warren 2020-09-24 11:28:13 -04:00
父節點 5b445add4b
當前提交 b7f39a5cf7
共有 1 個文件被更改,包括 71 次插入9 次删除

查看文件

@ -135,7 +135,36 @@ impl BigInt {
/// Only alphanumeric characters are considered, so exponents and
/// other forms are not parsed
pub fn from_str_radix<T: ToString>(s: T, radix: usize) -> BigInt {
let input = s.to_string();
let input = s.to_string().to_ascii_uppercase();
let input = input.trim();
assert!(
radix > 0 && radix <= 36,
"Radix must be between 1 and 36, inclusive. Given radix: {}",
radix
);
// In base 1, number of place values = total value
if radix == 1 {
let mut raw_digits: Vec<usize> = Vec::with_capacity(input.len());
for char in input.chars() {
match char {
'1' => raw_digits.push(1),
_ => continue,
}
}
return BigInt::from(raw_digits.len());
}
// If the number fits in a usize, try the easy way
let easy_res = usize::from_str_radix(input, radix as u32);
if easy_res.is_ok() {
return BigInt::from(easy_res.unwrap());
}
// TODO: consider parsing out the error, to tell if the
// parsed result is valid for the base
// Convert each digit to it's decimal representation
let mut raw_digits: Vec<usize> = Vec::with_capacity(input.len());
@ -148,8 +177,6 @@ impl BigInt {
// Calculate the decimal value by calculating the value
// of each place value
// In base 1, number of place values = total value
todo!();
}
@ -907,21 +934,56 @@ mod tests {
#[test]
#[should_panic]
fn test_from_str() {
fn test_from_str_large() {
let str = "ZYXWVUTSRQPONMLKJIHGFEDCBA987654321";
BigInt::from(str);
}
#[test]
fn test_from_str_small() {
let str = "012345";
BigInt::from(str);
let num = BigInt::from(str);
assert_eq!(num.inner[0], 12345usize);
}
#[test]
#[should_panic]
fn test_from_string() {
fn test_from_string_large() {
let str = String::from("ZYXWVUTSRQPONMLKJIHGFEDCBA987654321");
BigInt::from(str);
}
#[test]
fn test_from_string_small() {
let str = String::from("012345");
BigInt::from(str);
let num = BigInt::from(str);
assert_eq!(num.inner[0], 12345usize);
}
#[test]
fn test_from_str_radix_1() {
let s = "1".repeat(32);
let num = BigInt::from_str_radix(s, 1);
assert_eq!(num.inner[0], 32usize);
}
#[test]
#[should_panic]
fn test_from_str_radix() {
BigInt::from_str_radix("123456", 16);
fn test_from_str_radix_large() {
BigInt::from_str_radix("ZYXWVUTSRQPONMLKJIHGFEDCBA987654321", 36);
}
#[test]
fn test_from_str_radix_small() {
let num = BigInt::from_str_radix("FEDCBA", 16);
assert!(num.inner[0] > 0, "Number is not greater than 0");
assert!(num.inner[0] < usize::MAX, "Result is larger than usize");
assert_eq!(num.inner[0], 0xFEDCBAusize);
}
#[test]
fn test_from_str_radix_lowercase() {
let num = BigInt::from_str_radix("fedcba", 16);
assert_eq!(num.inner[0], 0xFEDCBAusize);
}
}