Alignment of floating point numbers printed in scientific notation

Viewed 921

I want to print floating-point numbers as a table as follows.

(ruby)

irb(main):001:0> printf("%10.3e  %10.3e\n%10.3e  %10.3e", 0.1111, 0.02222, 3333, -44444)
 1.111e-01   2.222e-02
 3.333e+03  -4.444e+04

However, in Rust, {:10.3e} format doesn't align e and .

fn main() {
  println!("{:10.3e}  {:10.3e}\n{:10.3e}  {:10.3e}", 0.1111, 0.02222, 3333, -44444);
}
  1.111e-1    2.222e-2
   3.333e3    -4.444e4

How should I format?

1 Answers

As Thomas mentioned in the comments, this isn't currently possible only using Rust's formatting parameters. So you'd have to implement your own utility formatting function (or find a crate that offers it).

Here's a quick-n-dirty solution I threw together:

fn fmt_f64(num: f64, width: usize, precision: usize, exp_pad: usize) -> String {
    let mut num = format!("{:.precision$e}", num, precision = precision);
    // Safe to `unwrap` as `num` is guaranteed to contain `'e'`
    let exp = num.split_off(num.find('e').unwrap());

    let (sign, exp) = if exp.starts_with("e-") {
        ('-', &exp[2..])
    } else {
        ('+', &exp[1..])
    };
    num.push_str(&format!("e{}{:0>pad$}", sign, exp, pad = exp_pad));

    format!("{:>width$}", num, width = width)
}
  • width controls the amount of left padded spaces
  • precision is the amount of decimals
  • exp_pad controls the amount of left padded 0s

Example:

fn main() {
    let nums = [
        0.1111,
        0.02222,
        3333.0,
        -44444.0,
        0.0,
        1.0,
        42.0,
        9999999999.00,
        999999999999.00,
        123456789.1011,
    ];

    for &num in &nums {
        println!("{}", fmt_f64(num, 10, 3, 2));
    }
}

Output:

 1.111e-01
 2.222e-02
 3.333e+03
-4.444e+04
 0.000e+00
 1.000e+00
 4.200e+01
 1.000e+10
 1.000e+12
 1.235e+08
Related