manual number parsing

This commit is contained in:
timeshifter
2026-07-09 17:13:15 +02:00
parent 20a16fcbe2
commit be1cf6b52b
2 changed files with 44 additions and 10 deletions
+2 -1
View File
@@ -3,4 +3,5 @@
107 nightly, build-std 107 nightly, build-std
109 native cpu (doesn't seem to work) 109 native cpu (doesn't seem to work)
95 FxHashMap 95 FxHashMap
75 mmap, reduced UTF8 parsing (names) 71 mmap, reduced UTF8 parsing (names)
50 manual number parsing
+42 -9
View File
@@ -30,13 +30,12 @@ fn main() {
let mut split = line.split(|&c| c == b';'); let mut split = line.split(|&c| c == b';');
let station = split.next().unwrap(); let station = split.next().unwrap();
let parsed: f64 = String::from_utf8(split.next().unwrap().to_vec()) let number = split.next().unwrap();
.unwrap() let parsed = parse_number(number);
.parse() // panic!();
.unwrap();
data.entry(station) data.entry(station)
.and_modify(|values: &mut (f64, f64, usize, f64)| { .and_modify(|values: &mut (i64, i64, usize, i64)| {
values.0 = values.0.min(parsed); values.0 = values.0.min(parsed);
values.1 += parsed; values.1 += parsed;
values.2 += 1; values.2 += 1;
@@ -48,7 +47,7 @@ fn main() {
} }
let mut stations: Vec<_> = data.keys().collect(); let mut stations: Vec<_> = data.keys().collect();
stations.sort(); stations.sort_unstable();
print!("{{"); print!("{{");
@@ -60,9 +59,9 @@ fn main() {
print!( print!(
"{s}={:.1}/{:.1}/{:.1}", "{s}={:.1}/{:.1}/{:.1}",
entry.0, entry.0 as f64 / 10.,
entry.1 / (entry.2 as f64), (entry.1 / (entry.2 as i64)) as f64 / 10.,
entry.3 entry.3 as f64 / 10.
); );
if iter.peek().is_some() { if iter.peek().is_some() {
print!(", "); print!(", ");
@@ -70,3 +69,37 @@ fn main() {
} }
println!("}}"); println!("}}");
} }
fn parse_number(number: &[u8]) -> i64 {
let sign = if *number.first().unwrap() == b'-' {
-1
} else {
1
};
let mut iter = number.iter().rev();
// 48: ASCII '0'
let mut result = (iter.next().unwrap() - 48) as i64;
iter.next(); // skip '.'
result += ((iter.next().unwrap() - 48) as i64) * 10;
if let Some(hundreds) = iter.next()
&& *hundreds != b'-'
{
result += ((hundreds - 48) as i64) * 100;
}
sign * result
}
#[cfg(test)]
mod tests {
use super::parse_number;
#[test]
fn test_parse_number() {
let input = [49, 53, 46, 51]; // "15.3"
assert_eq!(parse_number(&input), 153);
}
}