├── .github ├── FUNDING.yml └── workflows │ └── ci.yml ├── .gitignore ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── src └── lib.rs └── tests └── test.rs /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: dtolnay 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | workflow_dispatch: 7 | schedule: [cron: "40 1 * * *"] 8 | 9 | permissions: 10 | contents: read 11 | 12 | env: 13 | RUSTFLAGS: -Dwarnings 14 | 15 | jobs: 16 | pre_ci: 17 | uses: dtolnay/.github/.github/workflows/pre_ci.yml@master 18 | 19 | test: 20 | name: Rust ${{matrix.rust}} 21 | needs: pre_ci 22 | if: needs.pre_ci.outputs.continue 23 | runs-on: ubuntu-latest 24 | strategy: 25 | fail-fast: false 26 | matrix: 27 | rust: [nightly, beta, stable, 1.51.0] 28 | timeout-minutes: 45 29 | steps: 30 | - uses: actions/checkout@v4 31 | - uses: dtolnay/rust-toolchain@master 32 | with: 33 | toolchain: ${{matrix.rust}} 34 | - name: Enable type layout randomization 35 | run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV 36 | if: matrix.rust == 'nightly' 37 | - run: cargo test 38 | - uses: actions/upload-artifact@v4 39 | if: matrix.rust == 'nightly' && always() 40 | with: 41 | name: Cargo.lock 42 | path: Cargo.lock 43 | continue-on-error: true 44 | 45 | minimal: 46 | name: Minimal versions 47 | needs: pre_ci 48 | if: needs.pre_ci.outputs.continue 49 | runs-on: ubuntu-latest 50 | timeout-minutes: 45 51 | steps: 52 | - uses: actions/checkout@v4 53 | - uses: dtolnay/rust-toolchain@nightly 54 | - run: cargo generate-lockfile -Z minimal-versions 55 | - run: cargo check --locked 56 | 57 | doc: 58 | name: Documentation 59 | needs: pre_ci 60 | if: needs.pre_ci.outputs.continue 61 | runs-on: ubuntu-latest 62 | timeout-minutes: 45 63 | env: 64 | RUSTDOCFLAGS: -Dwarnings 65 | steps: 66 | - uses: actions/checkout@v4 67 | - uses: dtolnay/rust-toolchain@nightly 68 | - uses: dtolnay/install@cargo-docs-rs 69 | - run: cargo docs-rs 70 | 71 | clippy: 72 | name: Clippy 73 | runs-on: ubuntu-latest 74 | if: github.event_name != 'pull_request' 75 | timeout-minutes: 45 76 | steps: 77 | - uses: actions/checkout@v4 78 | - uses: dtolnay/rust-toolchain@clippy 79 | - run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic 80 | 81 | miri: 82 | name: Miri 83 | needs: pre_ci 84 | if: needs.pre_ci.outputs.continue 85 | runs-on: ubuntu-latest 86 | timeout-minutes: 45 87 | steps: 88 | - uses: actions/checkout@v4 89 | - uses: dtolnay/rust-toolchain@miri 90 | with: 91 | toolchain: nightly-2025-05-16 # https://github.com/rust-lang/miri/issues/4323 92 | - run: cargo miri setup 93 | - run: cargo miri test 94 | env: 95 | MIRIFLAGS: -Zmiri-strict-provenance 96 | 97 | outdated: 98 | name: Outdated 99 | runs-on: ubuntu-latest 100 | if: github.event_name != 'pull_request' 101 | timeout-minutes: 45 102 | steps: 103 | - uses: actions/checkout@v4 104 | - uses: dtolnay/rust-toolchain@stable 105 | - uses: dtolnay/install@cargo-outdated 106 | - run: cargo outdated --workspace --exit-code 1 107 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "precise" 3 | version = "0.1.10" 4 | authors = ["David Tolnay "] 5 | categories = ["value-formatting"] 6 | description = "Full precision decimal representation of f64" 7 | documentation = "https://docs.rs/precise" 8 | edition = "2018" 9 | keywords = ["float"] 10 | license = "MIT OR Apache-2.0" 11 | repository = "https://github.com/dtolnay/precise" 12 | rust-version = "1.51" 13 | 14 | [dependencies] 15 | num-bigint = "0.4.2" 16 | num-traits = "0.2" 17 | 18 | [package.metadata.docs.rs] 19 | targets = ["x86_64-unknown-linux-gnu"] 20 | rustdoc-args = [ 21 | "--generate-link-to-definition", 22 | "--extern-html-root-url=core=https://doc.rust-lang.org", 23 | "--extern-html-root-url=alloc=https://doc.rust-lang.org", 24 | "--extern-html-root-url=std=https://doc.rust-lang.org", 25 | ] 26 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Precise float to string 2 | ======================= 3 | 4 | [github](https://github.com/dtolnay/precise) 5 | [crates.io](https://crates.io/crates/precise) 6 | [docs.rs](https://docs.rs/precise) 7 | [build status](https://github.com/dtolnay/precise/actions?query=branch%3Amaster) 8 | 9 | This crate computes the decimal representation of the single rational number 10 | whose value is mathematically equal to a given float. 11 | 12 | *Note that this is almost never an appropriate way to print user-facing values. 13 | For that, use the [ryu] crate instead.* 14 | 15 | [ryu]: https://github.com/dtolnay/ryu 16 | 17 | ```toml 18 | [dependencies] 19 | precise = "0.1" 20 | ``` 21 | 22 | ## Example 23 | 24 | ```rust 25 | fn main() { 26 | // 0.1000000000000000055511151231257827021181583404541015625 27 | println!("{}", precise::to_string(0.1)); 28 | } 29 | ``` 30 | 31 |
32 | 33 | #### License 34 | 35 | 36 | Licensed under either of Apache License, Version 37 | 2.0 or MIT license at your option. 38 | 39 | 40 |
41 | 42 | 43 | Unless you explicitly state otherwise, any contribution intentionally submitted 44 | for inclusion in this crate by you, as defined in the Apache-2.0 license, shall 45 | be dual licensed as above, without any additional terms or conditions. 46 | 47 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! [![github]](https://github.com/dtolnay/precise) [![crates-io]](https://crates.io/crates/precise) [![docs-rs]](https://docs.rs/precise) 2 | //! 3 | //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github 4 | //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust 5 | //! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs 6 | //! 7 | //!
8 | //! 9 | //! Decimal representation of the single rational number whose value is 10 | //! mathematically equal to the input float. 11 | //! 12 | //! Note that this is almost never an appropriate way to print user-facing 13 | //! values. For that, use the [ryu] crate instead. 14 | //! 15 | //! [ryu]: https://github.com/dtolnay/ryu 16 | //! 17 | //! # Example 18 | //! 19 | //! ``` 20 | //! fn main() { 21 | //! // 0.1000000000000000055511151231257827021181583404541015625 22 | //! println!("{}", precise::to_string(0.1)); 23 | //! } 24 | //! ``` 25 | 26 | #![doc(html_root_url = "https://docs.rs/precise/0.1.10")] 27 | #![allow( 28 | clippy::must_use_candidate, 29 | clippy::needless_doctest_main, 30 | clippy::redundant_else, 31 | clippy::unseparated_literal_suffix 32 | )] 33 | 34 | use num_bigint::BigUint; 35 | use num_traits::Pow; 36 | 37 | pub fn to_string(n: impl traits::Float) -> String { 38 | traits::Float::to_precise_string(n) 39 | } 40 | 41 | mod traits { 42 | pub trait Float: Sized { 43 | fn to_precise_string(n: Self) -> String; 44 | } 45 | 46 | impl Float for f32 { 47 | fn to_precise_string(n: Self) -> String { 48 | crate::f32_to_precise_string(n) 49 | } 50 | } 51 | 52 | impl Float for f64 { 53 | fn to_precise_string(n: Self) -> String { 54 | crate::f64_to_precise_string(n) 55 | } 56 | } 57 | } 58 | 59 | fn f32_to_precise_string(n: f32) -> String { 60 | if n.is_nan() { 61 | return "NaN".to_owned(); 62 | } 63 | 64 | if n.is_infinite() { 65 | if n.is_sign_positive() { 66 | return "inf".to_owned(); 67 | } else { 68 | return "-inf".to_owned(); 69 | } 70 | } 71 | 72 | let bits = n.to_bits(); 73 | let is_negative = (bits & 0x8000_0000) != 0; 74 | let biased_exponent = (bits & 0x7F80_0000) >> 23; 75 | let significand = (bits & 0x007F_FFFF) + (1 << 23); 76 | 77 | // value 78 | // = significand * 2^(biased_exponent - 150) 79 | // = significand * 2^biased_exponent * 5^150 / 10^150 80 | let significand = BigUint::from(significand); 81 | let two = BigUint::from(2u8); 82 | let five = BigUint::from(5u8); 83 | let numerator = significand * two.pow(biased_exponent) * five.pow(150u16); 84 | 85 | let mut repr = numerator.to_string(); 86 | let more_zeros = 151usize.saturating_sub(repr.len()); 87 | let leading_zeros = "0".repeat(more_zeros); 88 | repr = leading_zeros + &repr; 89 | 90 | repr.insert(repr.len() - 150, '.'); 91 | repr.truncate(repr.trim_end_matches('0').len()); 92 | if repr.ends_with('.') { 93 | repr.push('0'); 94 | } 95 | 96 | if is_negative { 97 | repr.insert(0, '-'); 98 | } 99 | 100 | repr 101 | } 102 | 103 | fn f64_to_precise_string(n: f64) -> String { 104 | if n.is_nan() { 105 | return "NaN".to_owned(); 106 | } 107 | 108 | if n.is_infinite() { 109 | if n.is_sign_positive() { 110 | return "inf".to_owned(); 111 | } else { 112 | return "-inf".to_owned(); 113 | } 114 | } 115 | 116 | let bits = n.to_bits(); 117 | let is_negative = (bits & 0x8000_0000_0000_0000) != 0; 118 | let biased_exponent = (bits & 0x7FF0_0000_0000_0000) >> 52; 119 | let significand = (bits & 0x000F_FFFF_FFFF_FFFF) + (1 << 52); 120 | 121 | // value 122 | // = significand * 2^(biased_exponent - 1075) 123 | // = significand * 2^biased_exponent * 5^1075 / 10^1075 124 | let significand = BigUint::from(significand); 125 | let two = BigUint::from(2u8); 126 | let five = BigUint::from(5u8); 127 | let numerator = significand * two.pow(biased_exponent) * five.pow(1075u16); 128 | 129 | let mut repr = numerator.to_string(); 130 | let more_zeros = 1076usize.saturating_sub(repr.len()); 131 | let leading_zeros = "0".repeat(more_zeros); 132 | repr = leading_zeros + &repr; 133 | 134 | repr.insert(repr.len() - 1075, '.'); 135 | repr.truncate(repr.trim_end_matches('0').len()); 136 | if repr.ends_with('.') { 137 | repr.push('0'); 138 | } 139 | 140 | if is_negative { 141 | repr.insert(0, '-'); 142 | } 143 | 144 | repr 145 | } 146 | -------------------------------------------------------------------------------- /tests/test.rs: -------------------------------------------------------------------------------- 1 | #![allow( 2 | clippy::incompatible_msrv, // https://github.com/rust-lang/rust-clippy/issues/12257 3 | )] 4 | 5 | use std::f32; 6 | #[cfg(not(miri))] 7 | use std::f64; 8 | 9 | macro_rules! tests { 10 | ( 11 | $( 12 | $name:ident ( $float:expr ) = $expected:literal; 13 | )* 14 | ) => { 15 | $( 16 | #[test] 17 | fn $name() { 18 | assert_eq!(precise::to_string($float), $expected); 19 | } 20 | )* 21 | }; 22 | } 23 | 24 | tests! { 25 | _1_f32(1.0f32) = "1.0"; 26 | _90_f32(90.0f32) = "90.0"; 27 | 28 | _0_1_f32(0.1f32) = "0.100000001490116119384765625"; 29 | _0_123_f32(0.123f32) = "0.123000003397464752197265625"; 30 | _1_23_f32(1.23f32) = "1.230000019073486328125"; 31 | 32 | min_positive_f32(f32::MIN_POSITIVE) = "0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625"; 33 | min_f32(f32::MIN) = "-340282346638528859811704183484516925440.0"; 34 | max_f32(f32::MAX) = "340282346638528859811704183484516925440.0"; 35 | 36 | pos_nan_f32(f32::NAN.copysign(1.0)) = "NaN"; 37 | neg_nan_f32(f32::NAN.copysign(-1.0)) = "NaN"; 38 | pos_inf_f32(f32::INFINITY) = "inf"; 39 | neg_inf_f32(f32::NEG_INFINITY) = "-inf"; 40 | } 41 | 42 | #[cfg(not(miri))] 43 | tests! { 44 | _1_f64(1.0f64) = "1.0"; 45 | _90_f64(90.0f64) = "90.0"; 46 | 47 | _0_1_f64(0.1f64) = "0.1000000000000000055511151231257827021181583404541015625"; 48 | _0_123_f64(0.123f64) = "0.1229999999999999982236431605997495353221893310546875"; 49 | _1_23_f64(1.23f64) = "1.229999999999999982236431605997495353221893310546875"; 50 | 51 | min_positive_f64(f64::MIN_POSITIVE) = "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002225073858507201383090232717332404064219215980462331830553327416887204434813918195854283159012511020564067339731035811005152434161553460108856012385377718821130777993532002330479610147442583636071921565046942503734208375250806650616658158948720491179968591639648500635908770118304874799780887753749949451580451605050915399856582470818645113537935804992115981085766051992433352114352390148795699609591288891602992641511063466313393663477586513029371762047325631781485664350872122828637642044846811407613911477062801689853244110024161447421618567166150540154285084716752901903161322778896729707373123334086988983175067838846926092773977972858659654941091369095406136467568702398678315290680984617210924625396728515625"; 52 | min_f64(f64::MIN) = "-179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0"; 53 | max_f64(f64::MAX) = "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0"; 54 | 55 | pos_nan_f64(f64::NAN.copysign(1.0)) = "NaN"; 56 | neg_nan_f64(f64::NAN.copysign(-1.0)) = "NaN"; 57 | pos_inf_f64(f64::INFINITY) = "inf"; 58 | neg_inf_f64(f64::NEG_INFINITY) = "-inf"; 59 | } 60 | --------------------------------------------------------------------------------