Rust中使用Lexical解析带千位分隔符的浮点数问题
解析带千位分隔符的字符串为f64
问题背景
需要解析包含首尾空格、以逗号作为千位分隔符、点作为小数分隔符的字符串为f64类型。标准库的parse方法会因逗号报错,尝试使用lexical库配置自定义解析规则时也出现错误。
标准库尝试及报错
fn main() { let s: String = " 65,536.1415926535 ".to_string(); println!("{}", s); let f: f64 = s.trim().parse::<f64>().unwrap(); println!("{}", f); }
报错信息:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ParseFloatError { kind: Invalid }', src/main.rs:6:45 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Lexical库的错误尝试
直接调用lexical::parse仍报错:
use lexical; fn main() { let s: String = " 65,536.1415926535 ".to_string(); println!("{}", s); let f: f64 = lexical::parse( s.trim() ).unwrap(); println!("{}", f); }
报错信息:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: InvalidDigit(2)', src/main.rs:8:48 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
自定义格式配置时出现编译错误:
use lexical; use lexical_core; fn main() { const BRITISH: f64 = lexical::NumberFormatBuilder::new() .digit_separator(b',') .build() .unwrap(); let options = lexical_core::ParseFloatOptions::builder() .decimal_point(b'.') .build() .unwrap(); let s: String = " 65,536.1415926535 ".to_string(); println!("{}", s); let f: f64 = lexical::parse_with_options::<f64, BRITISH, _>( s.trim(), &options ).unwrap(); println!("{}", f); }
编译错误:
error[E0599]: no method named `digit_separator` found for struct `NumberFormatBuilder` in the current scope --> src/main.rs:7:10 | 6 | const BRITISH: f64 = lexical::NumberFormatBuilder::new() | __________________________- 7 | | .digit_separator(b',') | | -^^^^^^^^^^^^^^^ | | || | | |private field, not a method | |_________|help: there is a method with a similar name: `get_digit_separator` | error[E0747]: constant provided when a type was expected --> src/main.rs:19:56 | 19 | let f: f64 = lexical::parse_with_options::<f64, BRITISH, _>( s.trim(), &options ).unwrap();
解决方案
方法一:移除千位分隔符(简单直接)
直接移除字符串中的所有逗号,再用标准库解析,代码简洁无需额外依赖:
fn main() { let s: String = " 65,536.1415926535 ".to_string(); let cleaned = s.trim().replace(',', ""); let f: f64 = cleaned.parse().unwrap(); println!("{}", f); // 输出 65536.1415926535 }
方法二:正确使用Lexical库解析
Lexical的配置需注意版本规范,最新版本使用FormatBuilder统一配置分隔符,无需单独引入lexical_core。
首先在Cargo.toml添加依赖:
[dependencies] lexical = "6.1.1"
解析代码:
use lexical::{parse_with_options, FormatBuilder, ParseFloatOptions}; fn main() { let s = " 65,536.1415926535 "; // 配置千位分隔符为逗号,小数分隔符为点 let format = FormatBuilder::new() .digit_separator(b',') .decimal_point(b'.') .build() .unwrap(); let options = ParseFloatOptions::default(); let f: f64 = parse_with_options(s.trim(), &format, &options).unwrap(); println!("{}", f); // 输出 65536.1415926535 }
方法三:使用rust_decimal处理(高精度场景)
若需要更高精度的解析后再转换为f64,可使用rust_decimal库,它原生支持千位分隔符解析:
在Cargo.toml添加依赖:
[dependencies] rust_decimal = "1.34.0"
解析代码:
use rust_decimal::Decimal; use rust_decimal::parser::parse_str; fn main() { let s = " 65,536.1415926535 "; let decimal = parse_str(s.trim()).unwrap(); let f: f64 = decimal.into(); println!("{}", f); // 输出 65536.1415926535 }
内容的提问来源于stack exchange,提问作者mabalenk
相关产品推荐
相关产品推荐

