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