Как напечатать число с плавающей точкой Rust со всей доступной точностью?
Я реализую алгоритм CORDIC для sin
тригонометрическая функция. Чтобы сделать это, мне нужно жестко закодировать / вычислить кучу значений арктангенса. Прямо сейчас моя функция, кажется, работает (как подтверждено Wolfram Alpha) с точностью, которая напечатана, но я хотел бы иметь возможность печатать все 32 бита точности моего f32
, Как я могу это сделать?
fn generate_table() {
let pi: f32 = 3.1415926536897932384626;
let k1: f32 = 0.6072529350088812561694; // 1/k
let num_bits: uint = 32;
let num_elms: uint = num_bits;
let mul: uint = 1 << (num_bits - 2);
println!("Cordic sin in rust");
println!("num bits {}", num_bits);
println!("pi is {}", pi);
println!("k1 is {}", k1);
let shift: f32 = 2.0;
for ii in range(0, num_bits) {
let ipow: f32 = 1.0 / shift.powi(ii as i32);
let cur: f32 = ipow.atan();
println!("table values {}", cur);
}
}
6 ответов
Используйте спецификатор формата точности; .
сопровождаемое количеством десятичных знаков точности, которые вы хотели бы видеть:
fn main() {
let pi: f32 = 3.1415926536897932384626;
let k1: f32 = 0.6072529350088812561694; // 1/k
println!("pi is {:.32}", pi);
println!("k1 is {:.32}", k1);
}
Я выбрал 32, что больше, чем число десятичных знаков в любом из этих f32
s.
pi is 3.14159274101257324218750000000000
k1 is 0.60725295543670654296875000000000
Обратите внимание, что значения больше не совпадают; Значения с плавающей запятой сложны! Как уже упоминалось в комментарии, вы можете печатать как шестнадцатеричные или даже использовать свои литералы как шестнадцатеричные.
Использование точного формата спецификатора является правильным ответом, но для печати всей доступной точности просто воздержитесь от указания количества отображаемых цифр:
// prints 1
println!("{:.}", 1_f64);
// prints 0.000000000000000000000000123
println!("{:.}", 0.000000000000000000000000123_f64);
Таким образом, вы не будете усекать значения и не будете обрезать лишние нули, и отображение будет корректным для всех значений, независимо от того, являются они очень большими или очень маленькими.
Для полноты спецификатор формата точности также поддерживает указание фиксированной точности (согласно принятому ответу):
// prints 1.0000
println!("{:.4}", 1_f64);
а также точность, указанная во время выполнения (необязательно const
, конечно):
// prints 1.00
const PRECISION: usize = 2;
println!("{:.*}", PRECISION, 1_f64); // precision specifier immediately precedes positional argument
Этот ответ был написан для Rust 0.12.0 и не относится к Rust 1.x.
Вы можете использовать to_string
функция в std::f32
(не путать с to_string
метод):
fn main() {
println!("{}", std::f32::to_string(unsafe { std::mem::transmute::<i32, f32>(1) }));
println!("{}", std::f32::to_string(unsafe { std::mem::transmute::<i32, f32>(16) }));
println!("{}", std::f32::to_string(std::f32::MIN_POS_VALUE));
println!("{}", std::f32::to_string(std::f32::MAX_VALUE));
println!("{}", std::f32::to_string(std::f32::consts::PI));
}
Выход:
0.00000000000000000000000000000000000000000000140129852294921875
0.000000000000000000000000000000000000000000022420775890350341796875
0.000000000000000000000000000000000000011754944324493408203125
340282368002860660002286082464244022240
3.1415927410125732421875
Этот ответ был написан для Rust 0.12.0 и не относится к Rust 1.x.
Ты можешь использовать std::f32::to_string
распечатать все цифры.
use std::f32;
fn main() {
let pi: f32 = 3.1415926536897932384626;
let k1: f32 = 0.6072529350088812561694; // 1/k
println!("pi is {}", f32::to_string(pi));
println!("k1 is {}", f32::to_string(k1));
}
Выход:
pi is 3.1415927410125732421875
k1 is 0.607252979278564453125
Чтобы обрезать конечные нули и точки, вы можете сделать:
println!(
"number = {}",
format!("{:.2}", x).trim_end_matches(['.', '0'])
);
Примеры:
ИМХО нет способа обойти ящик bigdecimal, если вы хотите хранить числа с плавающей запятой с высокой точностью:
use bigdecimal::BigDecimal;
fn main() {
let pi = BigDecimal::parse_bytes(b"3.1415926536897932384626", 10);
let k1 = BigDecimal::parse_bytes(b"0.6072529350088812561694", 10); // 1/k
println!("pi is {pi:?}");
println!("k1 is {k1:?}");
}
получает:
pi is Some(BigDecimal("3.1415926536897932384626"))
k1 is Some(BigDecimal("0.6072529350088812561694"))