Search code examples
rustpercentage

Using integer math to get a percentage in Rust


I have to calculate some percentages but I have to avoid using floats in Rust.

i have this data structure

let data = Vec<Identity, u64>

from this i can sum all the u64's to get a total which we'll call the total maturity

let total_maturity = data.iter().map(|(,b)| b).sum()

so now i have the total maturity across all of them. it should be fairly trivial to get the percentage of maturity for each neuron but how i do i express this.

With floats it would be simple and the resulting vec of percentages associated with a neuron would be like [0.3, 0.4, 0.1 ....]

I've heard of using integer math but im not sure how it really works.


Solution

  • You can simply multiply all your numbers by 100 before dividing them.

    let data: Vec<u64> = vec![3, 4, 1, 2];
    let total_maturity: u64 = data.iter().sum();
    
    let percentages: Vec<u64> = data
        .iter()
        .map(|b| b * 100 / total_maturity)
        .collect();
    
    println!("{:?}", percentages);
    // [30, 40, 10, 20]
    

    If you need more precision, you can multiply by a larger number. Just remember that you will need to reintroduce the decimal point if you ever need to display them or perform math on them.

    let data: Vec<u64> = vec![3, 4, 1, 9992];
    let total_maturity: u64 = data.iter().sum();
    let percentages: Vec<u64> = data
        .iter()
        .map(|b| b * 10_000 / total_maturity)
        .collect();
    
    let formatted: Vec<String> = percentages
        .iter()
        .map(|&p| {
            let whole = p / 100;
            let frac = p % 100;
            format!("{whole}.{frac:.02}%")
            // or you could convert them to floats
            // format!("{}", p as f32 / 100.0)
        })
        .collect();
    
    println!("{:?}", formatted);
    // ["0.3%", "0.4%", "0.1%", "99.92%"]
    

    If you want something more flexible, there is the rust_decimal crate.