Is it possible to print a number formatted with thousand separator in Rust?

For instance

println!("{}", 10_000_000);

results in

10000000

whereas I'd like to format it to look something like

10,000,000

I went through the fmt module documentation, but there's nothing to cover this particular situation. I thought something like this would work

println!("{:,i}", 10_000_000);

but it throws an error

invalid format string: expected `}`, found `,`

There isn't, and there probably won't be.

Depending on where you are, the thousands separator may also work like 1,00,00,000 , or 1.000.000,000 or some other variant.

Localization isn't the job of the stdlib, plus format! is mostly handled at compile time (though to be fair this could be placed in its runtime portion easily), and you don't want to hard-bake a locale into the program.


Another workaround for this is to use the saparator crate which implements a .separated_string() method on float, integer and size types. Here is an example:

extern crate separator;
use separator::Separatable;

fn main() {
    let x1: u16 = 12345;
    let x2: u64 = 4242424242;
    let x3: u64 = 232323232323;
    println!("Unsigned ints:n{:>20}n{:>20}n{:>20}n", x1.separated_string(), x2.separated_string(), x3.separated_string());

    let x1: i16 = -12345;
    let x2: i64 = -4242424242;
    let x3: i64 = -232323232323;
    println!("Signed ints:n{:>20}n{:>20}n{:>20}n", x1.separated_string(), x2.separated_string(), x3.separated_string());


    let x1: f32 = -424242.4242;
    let x2: f64 = 23232323.2323;
    println!("Floats:n{:>20}n{:>20}n", x1.separated_string(), x2.separated_string());


    let x1: usize = 424242;
    // let x2: isize = -2323232323;  // Even though the docs say so, the traits seem not to be implemented for isize
    println!("Size types:n{:>20}n", x1.separated_string());        
}

Which gives you the following output:

Unsigned ints:
              12,345
       4,242,424,242
     232,323,232,323

Signed ints:
             -12,345
      -4,242,424,242
    -232,323,232,323

Floats:
         -424,242.44
     23,232,323.2323

Size types:
             424,242

Note that aligning floats like this is not easy since separated_string() returns a string. However, this is a relatively quick way to get separated numbers.


Regarding a custom function, I played around with this and here are some ideas:

use std::str;

fn main() {
    let i = 10_000_000i;
    println!("{}", decimal_mark1(i.to_string()));
    println!("{}", decimal_mark2(i.to_string()));
    println!("{}", decimal_mark3(i.to_string()));
}

fn decimal_mark1(s: String) -> String {
    let bytes: Vec<_> = s.bytes().rev().collect();
    let chunks: Vec<_> = bytes.chunks(3).map(|chunk| str::from_utf8(chunk).unwrap()).collect();
    let result: Vec<_> = chunks.connect(" ").bytes().rev().collect();
    String::from_utf8(result).unwrap()
}

fn decimal_mark2(s: String) -> String {
    let mut result = String::with_capacity(s.len() + ((s.len() - 1) / 3));
    let mut i = s.len();
    for c in s.chars() {
        result.push(c);
        i -= 1;
        if i > 0 && i % 3 == 0 {
            result.push(' ');
        }
    }
    result
}

fn decimal_mark3(s: String) -> String {
    let mut result = String::with_capacity(s.len() + ((s.len() - 1) / 3));
    let first = s.len() % 3;
    result.push_str(s.slice_to(first));
    for chunk in s.slice_from(first).as_bytes().chunks(3) {
        if !result.is_empty() {
            result.push(' ');
        }
        result.push_str(str::from_utf8(chunk).unwrap());
    }
    result
}

Playpen: http://is.gd/UigzCf

Comments welcome, none of them feels really nice.

链接地址: http://www.djcxy.com/p/82646.html

上一篇: 直接使用HashCode访问HashSet? (JAVA)

下一篇: 是否可以在Rust中打印一个用千位分隔符格式化的数字?