Выравнивание чисел с плавающей запятой, напечатанных в экспоненциальном представлении

Я хочу напечатать числа с плавающей запятой в виде таблицы следующим образом.

(Рубин)

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

Однако в Rust формат {:10.3e} не совпадает с e и ..

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

Как мне отформатировать?

Просматривая документацию и, в конце концов, исходный код, я почти уверен, что это невозможно из коробки. Вам нужно написать свою собственную оболочку newtype и реализовать на ней LowerExp. Даже тогда у Formatter, похоже, нет способа передать количество цифр для использования в показателе степени, поэтому вам придется жестко закодировать это как 2.

Thomas 12.12.2020 12:08
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
5
1
1 573
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как упомянул Томас в комментариях, в настоящее время это невозможно только с использованием параметров форматирования Rust . Таким образом, вам придется реализовать собственную функцию форматирования утилиты (или найти ящик, который ее предлагает).

Вот быстрое и грязное решение, которое я собрал:

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 контролирует количество пробелов слева
  • precision количество десятичных знаков
  • exp_pad контролирует количество левых заполненных 0s

Пример:

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));
    }
}

Выход:

 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

Другие вопросы по теме