Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I print a Rust floating-point number with all available precision?

I am implementing the CORDIC algorithm for the sin trigonometric function. In order to do this, I need to hardcode/calculate a bunch of arctangent values. Right now my function seems to work (as validated by Wolfram Alpha) to the precision that is printed, but I would like to be able to print all 32 bits of precision of my f32. How may I do that?

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);
    }
}
like image 670
Victory Avatar asked Oct 26 '14 19:10

Victory


2 Answers

Use the precision format specifier; a . followed by the number of decimal points of precision you'd like to see:

fn main() {
    let pi: f32 = 3.1415926536897932384626;
    let k1: f32 = 0.6072529350088812561694; // 1/k

    println!("pi is {:.32}", pi);
    println!("k1 is {:.32}", k1);
}

I chose 32, which is more than the number of decimal points in either of these f32s.

pi is 3.14159274101257324218750000000000
k1 is 0.60725295543670654296875000000000

Note that the values no longer match up; floating point values are difficult! As mentioned in a comment, you may wish to print as hexadecimal or even use your literals as hexadecimal.

like image 71
Shepmaster Avatar answered Oct 01 '22 12:10

Shepmaster


Using the precision format specifier is the correct answer, but to print all available precision, simply refrain from specifying the number of digits to display:

// prints 1
println!("{:.}", 1_f64);

// prints 0.000000000000000000000000123
println!("{:.}", 0.000000000000000000000000123_f64); 

This way, you will not truncate values nor will you have to trim excess zeros, and the display will be correct for all values, regardless of whether they are very large or very small.

Playground example

For completeness, the precision format specifier also supports a specifying a fixed precision (as per the accepted answer):

// prints 1.0000
println!("{:.4}", 1_f64);

as well as a precision specified at runtime (does not need to be const, of course):

// prints 1.00
const PRECISION: usize = 2;
println!("{:.*}", PRECISION, 1_f64); // precision specifier immediately precedes positional argument
like image 36
U007D Avatar answered Oct 01 '22 11:10

U007D