如何将浮点数舍入到指定的位数?

use*_*805 13 rust

如何将Rust中的f64浮点数舍入到指定的位数?

huo*_*uon 28

如果您只想将其用于显示目的,请使用内置println!()格式化语法.例如,要打印一个舍入到2位小数的数字,请使用{:.2}格式说明符:

fn main() {
    let x = 12.34567;
    println!("{:.2}", x);
}
Run Code Online (Sandbox Code Playgroud)

如果要将舍入数字放在字符串中,请使用format!().

如果你想要对一个数字进行舍入并将结果作为另一个数字返回,则将该数字乘以给定的10的幂,调用round并除以相同的幂,例如,舍入到2个小数位,使用10 2 = 100.

fn main() {
    let x = 12.34567_f64;
    let y = (x * 100.0).round() / 100.0;

    println!("{:.5} {:.5}", x, y);
}
Run Code Online (Sandbox Code Playgroud)

操场

这打印12.34567 12.35000.

如果在编译时不知道小数位数,则可以使用powi有效计算相关功率.

请注意,这将分解为非常大的数字; 具体地说,大于std::f64::MAX / power(其中power是10的幂,例如上面的例子中的100)的数字在乘法中将变为无穷大,并且在之后保持无穷大.但是,f64对于大于2 53的数字(即它们总是整数),不能代表任何小数位数,因此可以通过特殊情况将大数字返回给自己.

  • 你的 `(x * 100.0).round() / 100.0` 方法不仅会因为非常大的数字而崩溃。例如,“let x: f64 = 0.01499999999999999944488848768742172978818416595458984375”也是不正确的,它完全可以用“f64”表示,应该舍入到“0.01”,但舍入到“0.02”。 (4认同)
  • 我想知道为什么 `.round()` 中没有参数 - 我猜是因为 rust 没有默认/重载函数? (2认同)

iul*_*ian 28

添加到@huon 的好答案中,如果您想出于显示目的对浮点数进行舍入,但在编译时不知道精度,则可以使用精度格式化语法,如下所示:

fn main() {
    let precision = 3;
    let x = 12.34567;
    println!("{:.1$}", x, precision); // prints 12.346 and works with `format!` as well
}
Run Code Online (Sandbox Code Playgroud)

std::fmt的文档有更多关于语法的例子。


xin*_*nux 5

以小数计数作为参数的舍入函数示例:

fn round(x: f32, decimals: u32) -> f32 {
    let y = 10i32.pow(decimals) as f32;
    (x * y).round() / y
}
Run Code Online (Sandbox Code Playgroud)

  • `assert_eq!(round(4.365, 2), 4.37);` 失败 (6认同)

Tra*_*lug 5

在某些应用中,例如科学,四舍五入到有效数字比小数点后的数字更有意义。这是一个带有测试代码和文档的实现:

fn main() {
  println!("1230000.0 {} {}", 1230000.0, precision_f64(1230000.0, 2));
  println!("123000.0 {} {}", 123000.0, precision_f64(123000.0, 2));
  println!("12300.0 {} {}", 12300.0, precision_f64(12300.0, 2));
  println!("1230.0 {} {}", 1230.0, precision_f64(1230.0, 2));
  println!("123.00 {} {}", 123.00, precision_f64(123.00, 2));
  println!("12.300 {} {}", 12.300, precision_f64(12.300, 2));
  println!("1.2300 {} {}", 1.2300, precision_f64(1.2300, 2));
  println!(".12300 {} {}", 0.12300, precision_f64(0.12300, 2));
  println!(".01230 {} {}", 0.01230, precision_f64(0.01230, 2));
  println!(".00123 {} {}", 0.00123, precision_f64(0.00123, 2));
  println!("1.0000 {} {}", 1.00000, precision_f64(1.00000, 2));
}

/// Round to significant digits (rather than digits after the decimal).
///
/// Not implemented for `f32`, because such an implementation showed precision
/// glitches (e.g. `precision_f32(12300.0, 2) == 11999.999`), so for `f32`
/// floats, convert to `f64` for this function and back as needed.
///
/// Examples:
/// ```
///   precision_f64(1.2300, 2)                      // 1.2<f64>
///   precision_f64(1.2300_f64, 2)                  // 1.2<f64>
///   precision_f64(1.2300_f32 as f64, 2)           // 1.2<f64>
///   precision_f64(1.2300_f32 as f64, 2) as f32    // 1.2<f32>
/// ```
fn precision_f64(x: f64, decimals: u32) -> f64 {
  if x == 0. || decimals == 0 {
    0.
  } else {
    let shift = decimals as i32 - x.abs().log10().ceil() as i32;
    let shift_factor = 10_f64.powi(shift);

    (x * shift_factor).round() / shift_factor
  }
}
Run Code Online (Sandbox Code Playgroud)