Rust中如何将f64类型变量转换为usize类型?
Rust实现中位数计算:f64转usize问题及代码修复
核心问题:f64转usize的正确方式
Rust中f64没有直接的to_usize()方法,因为浮点数可能包含小数部分,转换时需要明确处理逻辑:
- 若确定浮点数为整数(或需截断小数):直接用
as转换,比如n as usize,但会直接丢弃小数部分。 - 需安全转换(检查范围、是否为整数):可手动实现校验逻辑,示例:
fn f64_to_usize(n: f64) -> Result<usize, &'static str> { if n.is_nan() || n.is_infinite() { return Err("Invalid float value"); } let n_int = n.round() as usize; if (n_int as f64) != n { return Err("Float is not an integer"); } Ok(n_int) }
不过在中位数计算场景中,完全不需要用浮点数计算索引,直接用整数除法更高效且避免转换问题,后续会详细说明。
代码中的其他问题及修复
1. 输入处理逻辑错误
输入"d"时,原代码中break会直接跳出循环,后续的打印和中位数计算代码永远不会执行,修复后:
// 原错误分支 Err(_) => if inp.trim() == String::from("q") { break; } else if inp.trim() == String::from("d"){ break { println!("Done!"); calc_med(); } } else { continue; } // 修复后分支 Err(_) => { match inp.trim() { "q" => break, "d" => { println!("Done!"); calc_med(); break; } _ => continue, } }
2. Mutex访问错误
v1是Mutex<Vec<f64>>,不能直接用v1[n2]访问元素,必须先获取锁的Guard:
// 原错误代码 let median: f64 = v1[n2]; // 修复后 let vec = v1.lock().unwrap(); let median = vec[n2];
3. 重复加锁降低性能
main函数中多次调用v1.lock().unwrap(),可合并为一次加锁,操作完成后自动释放:
// 原代码 v1.lock().unwrap().push(upd_inp); v1.lock().unwrap().sort_by(|a, b| a.partial_cmp(b).unwrap()); // 修复后 let mut vec = v1.lock().unwrap(); vec.push(upd_inp); vec.sort_by(|a, b| a.partial_cmp(b).unwrap());
4. 中位数计算逻辑错误
当前n = (len +1)/2的计算不符合中位数规则:
- 列表长度为奇数时,中位数是中间位置元素,索引为
len / 2(整数除法) - 列表长度为偶数时,中位数是中间两个元素的平均值:
(v[len/2 -1] + v[len/2]) / 2.0
完全不需要用浮点数计算索引,直接用整数操作即可。
修正后的完整代码
use std::io; use std::sync::Mutex; #[macro_use] extern crate lazy_static; lazy_static! { static ref v1: Mutex<Vec<f64>> = Mutex::new(Vec::new()); } fn main() { loop { println!("Enter a number, or 'q' to quit, 'd' to calculate median: "); let mut inp: String = String::new(); io::stdin().read_line(&mut inp).expect("Failed to read input"); let upd_inp: Result<f64, _> = inp.trim().parse(); match upd_inp { Ok(num) => { let mut vec = v1.lock().unwrap(); vec.push(num); vec.sort_by(|a, b| a.partial_cmp(b).unwrap()); println!("Current list: {:?}", vec); } Err(_) => { match inp.trim() { "q" => break, "d" => { println!("Done!"); calc_med(); break; } _ => { println!("Invalid input, please enter a number or 'q'/'d'"); continue; } } } }; } } fn calc_med() { let vec = v1.lock().unwrap(); let len = vec.len(); if len == 0 { println!("List is empty, no median"); return; } let median = if len % 2 == 1 { // 奇数长度,取中间元素 vec[len / 2] } else { // 偶数长度,取中间两个的平均值 (vec[len/2 - 1] + vec[len/2]) / 2.0 }; println!("Median: {}", median); }
说明
- 移除不必要的浮点数转换,用整数索引直接计算中位数,彻底避免f64转usize的问题
- 修复输入处理逻辑错误,确保输入
d时能正确触发中位数计算 - 合并Mutex重复加锁操作,提升程序性能
- 添加空列表的边界处理,避免索引越界
内容的提问来源于stack exchange,提问作者user20424877
相关产品推荐
相关产品推荐

