1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
//! [![github]](https://github.com/dtolnay/precise) [![crates-io]](https://crates.io/crates/precise) [![docs-rs]](https://docs.rs/precise) //! //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust //! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K //! //! <br> //! //! Decimal representation of the single rational number whose value is //! mathematically equal to the input float. //! //! Note that this is almost never an appropriate way to print user-facing //! values. For that, use the [ryu] crate instead. //! //! [ryu]: https://github.com/dtolnay/ryu //! //! # Example //! //! ``` //! fn main() { //! // 0.1000000000000000055511151231257827021181583404541015625 //! println!("{}", precise::to_string(0.1)); //! } //! ``` use num_bigint::BigUint; use num_traits::Pow; pub fn to_string(n: f64) -> String { if n.is_nan() { return "NaN".to_owned(); } if n.is_infinite() { if n.is_sign_positive() { return "inf".to_owned(); } else { return "-inf".to_owned(); } } let bits = n.to_bits(); let is_negative = (bits & 0x8000_0000_0000_0000) != 0; let biased_exponent = (bits & 0x7FF0_0000_0000_0000) >> 52; let significand = (bits & 0x000F_FFFF_FFFF_FFFF) + (1 << 52); // value // = significand * 2^(biased_exponent - 1075) // = significand * 2^biased_exponent * 5^1075 / 10^1075 let significand = BigUint::from(significand); let two = BigUint::from(2u8); let five = BigUint::from(5u8); let numerator = significand * two.pow(biased_exponent) * five.pow(1075u16); let mut repr = numerator.to_string(); let more_zeros = 1076usize.saturating_sub(repr.len()); let leading_zeros = "0".repeat(more_zeros); repr = leading_zeros + &repr; let point = repr.len() - 1075; repr = format!("{}.{}", &repr[..point], &repr[point..]); repr = repr.trim_end_matches('0').to_owned(); if repr.ends_with('.') { repr.push('0'); } if is_negative { repr.insert(0, '-'); } repr }