Skip to main content

malachite_float/float/conversion/string/
to_string.rs

1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::InnerFloat::Finite;
10use crate::float::conversion::string::get_str::get_str_ndigits;
11use crate::float::conversion::string::to_sci::to_sci_string;
12use crate::{ComparableFloat, ComparableFloatRef, Float};
13use core::fmt::{Binary, Debug, Display, Formatter, LowerHex, Octal, Result, UpperHex, Write};
14use malachite_base::num::arithmetic::traits::{DivRound, Mod, PowerOf2};
15use malachite_base::num::conversion::string::options::ToSciOptions;
16use malachite_base::num::conversion::traits::ExactFrom;
17use malachite_base::rounding_modes::RoundingMode::Ceiling;
18
19// The number of base-2^`digit_bits` digits that exactly cover a `Float` with binary exponent
20// `exponent` and precision `precision`, with the digits aligned to the base-2^`digit_bits` point:
21// the first digit holds `exponent mod digit_bits` significant bits (all `digit_bits` of them when
22// the exponent is a multiple), and the rest of the precision fills subsequent digits.
23fn power_of_2_digit_count(exponent: i32, precision: u64, digit_bits: u64) -> u64 {
24    let m = u64::exact_from(exponent.mod_op(i32::exact_from(digit_bits)));
25    let mut count = precision.saturating_sub(m).div_round(digit_bits, Ceiling).0;
26    if m != 0 {
27        count += 1;
28    }
29    count
30}
31
32// Writes `x` in the base 2^`digit_bits`, with exactly enough digits to represent it. When the
33// formatter's alternate flag is set, `prefix` follows the sign for zero and finite values (but not
34// NaN or the infinities).
35fn fmt_power_of_2_base(
36    x: &Float,
37    f: &mut Formatter,
38    digit_bits: u64,
39    uppercase: bool,
40    prefix: &str,
41) -> Result {
42    let mut options = ToSciOptions::default();
43    options.set_base(u8::power_of_2(digit_bits));
44    options.set_e_uppercase();
45    if uppercase {
46        options.set_uppercase();
47    }
48    if let Float(Finite {
49        exponent,
50        precision,
51        ..
52    }) = x
53    {
54        options.set_precision(power_of_2_digit_count(*exponent, *precision, digit_bits));
55        options.set_include_trailing_zeros(true);
56    }
57    let s = to_sci_string(x, options);
58    if !x.is_nan() && !x.is_infinite() {
59        let (sign, body) = match s.strip_prefix('-') {
60            Some(body) => ("-", body),
61            None => ("", s.as_str()),
62        };
63        f.write_str(sign)?;
64        if f.alternate() {
65            f.write_str(prefix)?;
66        }
67        f.write_str(body)
68    } else {
69        f.write_str(&s)
70    }
71}
72
73impl Display for Float {
74    /// Converts a [`Float`] to a [`String`].
75    ///
76    /// The output has enough digits to round-trip: a [`Float`] of precision $p$ is written with
77    /// $1+\lceil p \log_{10} 2 \rceil$ significant digits, correctly rounded to nearest. That count
78    /// depends only on the precision, so it is the same for every value of a given precision, and
79    /// trailing zeros are kept to reach it; a value of precision 1 prints as `"1.0"` where the same
80    /// value at precision 100 prints as `"1.0000000000000000000000000000000"`. A printed string
81    /// therefore does not by itself determine a [`Float`]; see [`ComparableFloat`], whose output
82    /// also records the precision.
83    ///
84    /// The output of a finite value always contains a point. Values whose exponent is far from zero
85    /// use scientific notation, zeros are `0.0` and `-0.0`, and the special values are `NaN`,
86    /// `Infinity`, and `-Infinity`.
87    ///
88    /// # Worst-case complexity
89    /// $T(n) = O(n (\log n)^2 \log\log n)$
90    ///
91    /// $M(n) = O(n \log n)$
92    ///
93    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.complexity()`.
94    ///
95    /// # Examples
96    /// ```
97    /// use malachite_base::num::arithmetic::traits::PowerOf2;
98    /// use malachite_base::num::basic::traits::{
99    ///     Infinity, NaN, NegativeInfinity, NegativeZero, One, Zero,
100    /// };
101    /// use malachite_float::Float;
102    ///
103    /// assert_eq!(Float::NAN.to_string(), "NaN");
104    /// assert_eq!(Float::INFINITY.to_string(), "Infinity");
105    /// assert_eq!(Float::NEGATIVE_INFINITY.to_string(), "-Infinity");
106    /// assert_eq!(Float::ZERO.to_string(), "0.0");
107    /// assert_eq!(Float::NEGATIVE_ZERO.to_string(), "-0.0");
108    ///
109    /// assert_eq!(Float::ONE.to_string(), "1.0");
110    /// assert_eq!(Float::from(1.5).to_string(), "1.5");
111    /// assert_eq!(Float::from(255).to_string(), "255.0");
112    /// assert_eq!(
113    ///     Float::from(core::f64::consts::PI).to_string(),
114    ///     "3.1415926535897931"
115    /// );
116    ///
117    /// // The digit count is determined by the precision, not by the value.
118    /// assert_eq!(
119    ///     Float::one_prec(100).to_string(),
120    ///     "1.0000000000000000000000000000000"
121    /// );
122    ///
123    /// // Values far from 1 use scientific notation.
124    /// assert_eq!(Float::power_of_2(100u64).to_string(), "1.3e30");
125    /// assert_eq!(Float::power_of_2(-100i64).to_string(), "7.9e-31");
126    /// ```
127    fn fmt(&self, f: &mut Formatter) -> Result {
128        let mut options = ToSciOptions::default();
129        if let Self(Finite { precision, .. }) = self {
130            options.set_precision(u64::exact_from(get_str_ndigits(10, *precision)));
131            options.set_include_trailing_zeros(true);
132        }
133        f.write_str(&to_sci_string(self, options))
134    }
135}
136
137impl Debug for Float {
138    /// Converts a [`Float`] to a [`String`].
139    ///
140    /// This is the same implementation as for [`Display`].
141    ///
142    /// # Worst-case complexity
143    /// $T(n) = O(n (\log n)^2 \log\log n)$
144    ///
145    /// $M(n) = O(n \log n)$
146    ///
147    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.complexity()`.
148    ///
149    /// # Examples
150    /// ```
151    /// use malachite_base::num::basic::traits::{NaN, One, Zero};
152    /// use malachite_base::strings::ToDebugString;
153    /// use malachite_float::Float;
154    ///
155    /// assert_eq!(Float::NAN.to_debug_string(), "NaN");
156    /// assert_eq!(Float::ZERO.to_debug_string(), "0.0");
157    /// assert_eq!(Float::ONE.to_debug_string(), "1.0");
158    /// assert_eq!(Float::from(1.5).to_debug_string(), "1.5");
159    /// ```
160    #[inline]
161    fn fmt(&self, f: &mut Formatter) -> Result {
162        Display::fmt(self, f)
163    }
164}
165
166impl Binary for Float {
167    /// Converts a [`Float`] to a binary [`String`].
168    ///
169    /// Using the `#` format flag prepends `"0b"` to the string, after any sign.
170    ///
171    /// Two is a power of two, so every [`Float`] is exactly representable in this base: the output
172    /// has exactly as many digits as are needed to write the value, one per bit of precision, and
173    /// is never rounded. The exponent, when one is shown, is a decimal number following an `E`.
174    ///
175    /// # Worst-case complexity
176    /// $T(n) = O(n)$
177    ///
178    /// $M(n) = O(n)$
179    ///
180    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.complexity()`.
181    ///
182    /// # Examples
183    /// ```
184    /// use malachite_base::num::arithmetic::traits::PowerOf2;
185    /// use malachite_base::num::basic::traits::{NaN, One, Zero};
186    /// use malachite_base::strings::ToBinaryString;
187    /// use malachite_float::Float;
188    ///
189    /// assert_eq!(Float::NAN.to_binary_string(), "NaN");
190    /// assert_eq!(Float::ZERO.to_binary_string(), "0.0");
191    /// assert_eq!(Float::ONE.to_binary_string(), "1.0");
192    /// assert_eq!(Float::from(1.5).to_binary_string(), "1.1");
193    /// assert_eq!(Float::from(255).to_binary_string(), "11111111.0");
194    /// assert_eq!(Float::power_of_2(100u64).to_binary_string(), "1.0E100");
195    ///
196    /// assert_eq!(format!("{:#b}", Float::ZERO), "0b0.0");
197    /// assert_eq!(format!("{:#b}", Float::from(1.5)), "0b1.1");
198    /// assert_eq!(format!("{:#b}", Float::from(-1.5)), "-0b1.1");
199    /// // The specials are never prefixed.
200    /// assert_eq!(format!("{:#b}", Float::NAN), "NaN");
201    /// ```
202    #[inline]
203    fn fmt(&self, f: &mut Formatter) -> Result {
204        fmt_power_of_2_base(self, f, 1, false, "0b")
205    }
206}
207
208impl Octal for Float {
209    /// Converts a [`Float`] to an octal [`String`].
210    ///
211    /// Using the `#` format flag prepends `"0o"` to the string, after any sign.
212    ///
213    /// Eight is a power of two, so every [`Float`] is exactly representable in this base: the
214    /// output has exactly as many digits as are needed to write the value, and is never rounded.
215    /// The exponent, when one is shown, is a decimal number following an `E`.
216    ///
217    /// # Worst-case complexity
218    /// $T(n) = O(n)$
219    ///
220    /// $M(n) = O(n)$
221    ///
222    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.complexity()`.
223    ///
224    /// # Examples
225    /// ```
226    /// use malachite_base::num::arithmetic::traits::PowerOf2;
227    /// use malachite_base::num::basic::traits::{NaN, One, Zero};
228    /// use malachite_base::strings::ToOctalString;
229    /// use malachite_float::Float;
230    ///
231    /// assert_eq!(Float::NAN.to_octal_string(), "NaN");
232    /// assert_eq!(Float::ZERO.to_octal_string(), "0.0");
233    /// assert_eq!(Float::ONE.to_octal_string(), "1.0");
234    /// assert_eq!(Float::from(1.5).to_octal_string(), "1.4");
235    /// assert_eq!(Float::from(255).to_octal_string(), "377.0");
236    /// assert_eq!(Float::power_of_2(100u64).to_octal_string(), "2.0E33");
237    ///
238    /// assert_eq!(format!("{:#o}", Float::ZERO), "0o0.0");
239    /// assert_eq!(format!("{:#o}", Float::from(1.5)), "0o1.4");
240    /// assert_eq!(format!("{:#o}", Float::from(-1.5)), "-0o1.4");
241    /// ```
242    #[inline]
243    fn fmt(&self, f: &mut Formatter) -> Result {
244        fmt_power_of_2_base(self, f, 3, false, "0o")
245    }
246}
247
248impl LowerHex for Float {
249    /// Converts a [`Float`] to a hexadecimal [`String`], using lowercase digits.
250    ///
251    /// Using the `#` format flag prepends `"0x"` to the string, after any sign.
252    ///
253    /// Sixteen is a power of two, so every [`Float`] is exactly representable in this base: the
254    /// output has exactly as many digits as are needed to write the value, and is never rounded.
255    /// The exponent, when one is shown, is a decimal number following an `E`.
256    ///
257    /// # Worst-case complexity
258    /// $T(n) = O(n)$
259    ///
260    /// $M(n) = O(n)$
261    ///
262    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.complexity()`.
263    ///
264    /// # Examples
265    /// ```
266    /// use malachite_base::num::arithmetic::traits::PowerOf2;
267    /// use malachite_base::num::basic::traits::{NaN, One, Zero};
268    /// use malachite_base::strings::ToLowerHexString;
269    /// use malachite_float::Float;
270    ///
271    /// assert_eq!(Float::NAN.to_lower_hex_string(), "NaN");
272    /// assert_eq!(Float::ZERO.to_lower_hex_string(), "0.0");
273    /// assert_eq!(Float::ONE.to_lower_hex_string(), "1.0");
274    /// assert_eq!(Float::from(1.5).to_lower_hex_string(), "1.8");
275    /// assert_eq!(Float::from(255).to_lower_hex_string(), "ff.0");
276    /// assert_eq!(Float::power_of_2(100u64).to_lower_hex_string(), "1.0E+25");
277    ///
278    /// assert_eq!(format!("{:#x}", Float::ZERO), "0x0.0");
279    /// assert_eq!(format!("{:#x}", Float::from(1.5)), "0x1.8");
280    /// assert_eq!(format!("{:#x}", Float::from(-1.5)), "-0x1.8");
281    /// ```
282    #[inline]
283    fn fmt(&self, f: &mut Formatter) -> Result {
284        fmt_power_of_2_base(self, f, 4, false, "0x")
285    }
286}
287
288impl UpperHex for Float {
289    /// Converts a [`Float`] to a hexadecimal [`String`], using uppercase digits.
290    ///
291    /// Using the `#` format flag prepends `"0x"` to the string, after any sign. As for the
292    /// primitive integers, the prefix stays lowercase.
293    ///
294    /// This is the same as [`LowerHex`] apart from the case of the digits; see it for the
295    /// properties of the base.
296    ///
297    /// # Worst-case complexity
298    /// $T(n) = O(n)$
299    ///
300    /// $M(n) = O(n)$
301    ///
302    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.complexity()`.
303    ///
304    /// # Examples
305    /// ```
306    /// use malachite_base::num::basic::traits::{NaN, One, Zero};
307    /// use malachite_base::strings::ToUpperHexString;
308    /// use malachite_float::Float;
309    ///
310    /// assert_eq!(Float::NAN.to_upper_hex_string(), "NaN");
311    /// assert_eq!(Float::ZERO.to_upper_hex_string(), "0.0");
312    /// assert_eq!(Float::ONE.to_upper_hex_string(), "1.0");
313    /// assert_eq!(Float::from(1.5).to_upper_hex_string(), "1.8");
314    /// assert_eq!(Float::from(255).to_upper_hex_string(), "FF.0");
315    ///
316    /// assert_eq!(format!("{:#X}", Float::from(255)), "0xFF.0");
317    /// assert_eq!(format!("{:#X}", Float::from(-1.5)), "-0x1.8");
318    /// ```
319    #[inline]
320    fn fmt(&self, f: &mut Formatter) -> Result {
321        fmt_power_of_2_base(self, f, 4, true, "0x")
322    }
323}
324
325impl Display for ComparableFloat {
326    /// Converts a [`ComparableFloat`] to a [`String`].
327    ///
328    /// This is the same implementation as for [`ComparableFloatRef`]: the wrapped [`Float`]'s
329    /// [`Display`] output, followed by `#` and the precision.
330    ///
331    /// # Worst-case complexity
332    /// $T(n) = O(n (\log n)^2 \log\log n)$
333    ///
334    /// $M(n) = O(n \log n)$
335    ///
336    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
337    ///
338    /// # Examples
339    /// ```
340    /// use malachite_base::num::basic::traits::One;
341    /// use malachite_float::{ComparableFloat, Float};
342    ///
343    /// assert_eq!(ComparableFloat(Float::ONE).to_string(), "1.0#1");
344    /// assert_eq!(ComparableFloat(Float::one_prec(100)).to_string().len(), 37);
345    /// assert_eq!(ComparableFloat(Float::from(1.5)).to_string(), "1.5#2");
346    /// ```
347    #[inline]
348    fn fmt(&self, f: &mut Formatter) -> Result {
349        Display::fmt(&ComparableFloatRef(&self.0), f)
350    }
351}
352
353impl Debug for ComparableFloat {
354    /// Converts a [`ComparableFloat`] to a [`String`].
355    ///
356    /// This is the same implementation as for [`Display`].
357    ///
358    /// # Worst-case complexity
359    /// $T(n) = O(n (\log n)^2 \log\log n)$
360    ///
361    /// $M(n) = O(n \log n)$
362    ///
363    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
364    ///
365    /// # Examples
366    /// ```
367    /// use malachite_base::num::basic::traits::One;
368    /// use malachite_base::strings::ToDebugString;
369    /// use malachite_float::{ComparableFloat, Float};
370    ///
371    /// assert_eq!(ComparableFloat(Float::ONE).to_debug_string(), "1.0#1");
372    /// assert_eq!(ComparableFloat(Float::from(1.5)).to_debug_string(), "1.5#2");
373    /// ```
374    #[inline]
375    fn fmt(&self, f: &mut Formatter) -> Result {
376        Debug::fmt(&ComparableFloatRef(&self.0), f)
377    }
378}
379
380impl LowerHex for ComparableFloat {
381    /// Converts a [`ComparableFloat`] to a hexadecimal [`String`].
382    ///
383    /// This is the same implementation as for [`ComparableFloatRef`]: the wrapped [`Float`]'s
384    /// [`LowerHex`] output, followed by `#` and the precision. Using the `#` format flag prepends
385    /// `"0x"` to the value, after any sign.
386    ///
387    /// This is the form that identifies a [`Float`] exactly, and the one the tests use as their
388    /// canonical label: the digits are exact because the base is a power of two, and the suffix
389    /// records the precision, which the digits alone may not determine.
390    ///
391    /// # Worst-case complexity
392    /// $T(n) = O(n)$
393    ///
394    /// $M(n) = O(n)$
395    ///
396    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
397    ///
398    /// # Examples
399    /// ```
400    /// use malachite_base::num::basic::traits::One;
401    /// use malachite_float::{ComparableFloat, Float};
402    ///
403    /// assert_eq!(format!("{:x}", ComparableFloat(Float::ONE)), "1.0#1");
404    /// assert_eq!(format!("{:#x}", ComparableFloat(Float::ONE)), "0x1.0#1");
405    /// assert_eq!(
406    ///     format!("{:#x}", ComparableFloat(Float::from(1.5))),
407    ///     "0x1.8#2"
408    /// );
409    /// assert_eq!(
410    ///     format!("{:#x}", ComparableFloat(Float::from(-1.5))),
411    ///     "-0x1.8#2"
412    /// );
413    /// ```
414    #[inline]
415    fn fmt(&self, f: &mut Formatter) -> Result {
416        LowerHex::fmt(&ComparableFloatRef(&self.0), f)
417    }
418}
419
420impl Binary for ComparableFloat {
421    /// Converts a [`ComparableFloat`] to a binary [`String`].
422    ///
423    /// This is the same implementation as for [`ComparableFloatRef`]: the wrapped [`Float`]'s
424    /// [`Binary`] output, followed by `#` and the precision. Using the `#` format flag prepends
425    /// `"0b"` to the value, after any sign.
426    ///
427    /// # Worst-case complexity
428    /// $T(n) = O(n)$
429    ///
430    /// $M(n) = O(n)$
431    ///
432    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
433    ///
434    /// # Examples
435    /// ```
436    /// use malachite_base::num::basic::traits::One;
437    /// use malachite_float::{ComparableFloat, Float};
438    ///
439    /// assert_eq!(format!("{:b}", ComparableFloat(Float::ONE)), "1.0#1");
440    /// assert_eq!(format!("{:#b}", ComparableFloat(Float::ONE)), "0b1.0#1");
441    /// assert_eq!(
442    ///     format!("{:#b}", ComparableFloat(Float::from(-1.5))),
443    ///     "-0b1.1#2"
444    /// );
445    /// ```
446    #[inline]
447    fn fmt(&self, f: &mut Formatter) -> Result {
448        Binary::fmt(&ComparableFloatRef(&self.0), f)
449    }
450}
451
452impl Octal for ComparableFloat {
453    /// Converts a [`ComparableFloat`] to an octal [`String`].
454    ///
455    /// This is the same implementation as for [`ComparableFloatRef`]: the wrapped [`Float`]'s
456    /// [`Octal`] output, followed by `#` and the precision. Using the `#` format flag prepends
457    /// `"0o"` to the value, after any sign.
458    ///
459    /// # Worst-case complexity
460    /// $T(n) = O(n)$
461    ///
462    /// $M(n) = O(n)$
463    ///
464    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
465    ///
466    /// # Examples
467    /// ```
468    /// use malachite_base::num::basic::traits::One;
469    /// use malachite_float::{ComparableFloat, Float};
470    ///
471    /// assert_eq!(format!("{:o}", ComparableFloat(Float::ONE)), "1.0#1");
472    /// assert_eq!(format!("{:#o}", ComparableFloat(Float::ONE)), "0o1.0#1");
473    /// assert_eq!(
474    ///     format!("{:#o}", ComparableFloat(Float::from(-1.5))),
475    ///     "-0o1.4#2"
476    /// );
477    /// ```
478    #[inline]
479    fn fmt(&self, f: &mut Formatter) -> Result {
480        Octal::fmt(&ComparableFloatRef(&self.0), f)
481    }
482}
483
484impl UpperHex for ComparableFloat {
485    /// Converts a [`ComparableFloat`] to a hexadecimal [`String`].
486    ///
487    /// This is the same implementation as for [`ComparableFloatRef`]: the wrapped [`Float`]'s
488    /// [`UpperHex`] output, followed by `#` and the precision. Using the `#` format flag prepends
489    /// `"0x"` to the value, after any sign.
490    ///
491    /// # Worst-case complexity
492    /// $T(n) = O(n)$
493    ///
494    /// $M(n) = O(n)$
495    ///
496    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
497    ///
498    /// # Examples
499    /// ```
500    /// use malachite_base::num::basic::traits::One;
501    /// use malachite_float::{ComparableFloat, Float};
502    ///
503    /// assert_eq!(format!("{:X}", ComparableFloat(Float::ONE)), "1.0#1");
504    /// assert_eq!(format!("{:#X}", ComparableFloat(Float::ONE)), "0x1.0#1");
505    /// assert_eq!(
506    ///     format!("{:#X}", ComparableFloat(Float::from(255))),
507    ///     "0xFF.0#8"
508    /// );
509    /// ```
510    #[inline]
511    fn fmt(&self, f: &mut Formatter) -> Result {
512        UpperHex::fmt(&ComparableFloatRef(&self.0), f)
513    }
514}
515
516impl Display for ComparableFloatRef<'_> {
517    /// Converts a [`ComparableFloatRef`] to a [`String`].
518    ///
519    /// The output is the wrapped [`Float`]'s [`Display`] output, followed by `#` and the precision,
520    /// as in `"1.5#2"`. Because a [`Float`]'s decimal digits do not determine its precision, the
521    /// suffix is what makes the output identify the value that [`ComparableFloatRef`]'s [`Eq`]
522    /// compares. The special values and the zeros have no precision, so they are written exactly as
523    /// [`Float`] writes them.
524    ///
525    /// # Worst-case complexity
526    /// $T(n) = O(n (\log n)^2 \log\log n)$
527    ///
528    /// $M(n) = O(n \log n)$
529    ///
530    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
531    ///
532    /// # Examples
533    /// ```
534    /// use malachite_base::num::basic::traits::{NaN, One, Zero};
535    /// use malachite_float::{ComparableFloatRef, Float};
536    ///
537    /// assert_eq!(ComparableFloatRef(&Float::ONE).to_string(), "1.0#1");
538    /// assert_eq!(ComparableFloatRef(&Float::from(1.5)).to_string(), "1.5#2");
539    /// assert_eq!(ComparableFloatRef(&Float::from(255)).to_string(), "255.0#8");
540    ///
541    /// // The specials and the zeros carry no precision.
542    /// assert_eq!(ComparableFloatRef(&Float::NAN).to_string(), "NaN");
543    /// assert_eq!(ComparableFloatRef(&Float::ZERO).to_string(), "0.0");
544    /// ```
545    fn fmt(&self, f: &mut Formatter) -> Result {
546        if let x @ Float(Finite { precision, .. }) = &self.0 {
547            write!(f, "{x}")?;
548            f.write_char('#')?;
549            write!(f, "{precision}")
550        } else {
551            Display::fmt(&self.0, f)
552        }
553    }
554}
555
556impl LowerHex for ComparableFloatRef<'_> {
557    /// Converts a [`ComparableFloatRef`] to a hexadecimal [`String`].
558    ///
559    /// The output is the wrapped [`Float`]'s [`LowerHex`] output, followed by `#` and the
560    /// precision, as in `"1.8#2"`. Using the `#` format flag prepends `"0x"` to the value, after
561    /// any sign, giving `"0x1.8#2"`.
562    ///
563    /// This is the form that identifies a [`Float`] exactly: the digits are exact because the base
564    /// is a power of two, and the suffix supplies the precision. It is also what a base-16
565    /// [`FromStringBase`](malachite_base::num::conversion::traits::FromStringBase) parse accepts,
566    /// so the two round-trip, which is why the tests use it as their canonical label.
567    ///
568    /// # Worst-case complexity
569    /// $T(n) = O(n)$
570    ///
571    /// $M(n) = O(n)$
572    ///
573    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
574    ///
575    /// # Examples
576    /// ```
577    /// use malachite_base::num::basic::traits::{NaN, One};
578    /// use malachite_float::{ComparableFloatRef, Float};
579    ///
580    /// assert_eq!(format!("{:x}", ComparableFloatRef(&Float::ONE)), "1.0#1");
581    /// assert_eq!(format!("{:#x}", ComparableFloatRef(&Float::ONE)), "0x1.0#1");
582    /// assert_eq!(
583    ///     format!("{:#x}", ComparableFloatRef(&Float::from(1.5))),
584    ///     "0x1.8#2"
585    /// );
586    /// assert_eq!(
587    ///     format!("{:#x}", ComparableFloatRef(&Float::from(255))),
588    ///     "0xff.0#8"
589    /// );
590    /// assert_eq!(format!("{:#x}", ComparableFloatRef(&Float::NAN)), "NaN");
591    /// ```
592    fn fmt(&self, f: &mut Formatter) -> Result {
593        if let x @ Float(Finite { precision, .. }) = &self.0 {
594            if f.alternate() {
595                write!(f, "{x:#x}")?;
596            } else {
597                write!(f, "{x:x}")?;
598            }
599            f.write_char('#')?;
600            write!(f, "{precision}")
601        } else {
602            LowerHex::fmt(&self.0, f)
603        }
604    }
605}
606
607impl Binary for ComparableFloatRef<'_> {
608    /// Converts a [`ComparableFloatRef`] to a binary [`String`].
609    ///
610    /// The output is the wrapped [`Float`]'s [`Binary`] output, followed by `#` and the precision.
611    /// Using the `#` format flag prepends `"0b"` to the value, after any sign.
612    ///
613    /// Like the hexadecimal form, this identifies a [`Float`] exactly: the digits are exact because
614    /// the base is a power of two, and the suffix supplies the precision, which the digits alone
615    /// may not determine.
616    ///
617    /// # Worst-case complexity
618    /// $T(n) = O(n)$
619    ///
620    /// $M(n) = O(n)$
621    ///
622    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
623    ///
624    /// # Examples
625    /// ```
626    /// use malachite_base::num::basic::traits::{NaN, One};
627    /// use malachite_float::{ComparableFloatRef, Float};
628    ///
629    /// assert_eq!(format!("{:b}", ComparableFloatRef(&Float::ONE)), "1.0#1");
630    /// assert_eq!(format!("{:#b}", ComparableFloatRef(&Float::ONE)), "0b1.0#1");
631    /// assert_eq!(
632    ///     format!("{:#b}", ComparableFloatRef(&Float::from(1.5))),
633    ///     "0b1.1#2"
634    /// );
635    /// assert_eq!(
636    ///     format!("{:#b}", ComparableFloatRef(&Float::from(255))),
637    ///     "0b11111111.0#8"
638    /// );
639    /// assert_eq!(format!("{:#b}", ComparableFloatRef(&Float::NAN)), "NaN");
640    /// ```
641    fn fmt(&self, f: &mut Formatter) -> Result {
642        if let x @ Float(Finite { precision, .. }) = &self.0 {
643            if f.alternate() {
644                write!(f, "{x:#b}")?;
645            } else {
646                write!(f, "{x:b}")?;
647            }
648            f.write_char('#')?;
649            write!(f, "{precision}")
650        } else {
651            Binary::fmt(&self.0, f)
652        }
653    }
654}
655
656impl Octal for ComparableFloatRef<'_> {
657    /// Converts a [`ComparableFloatRef`] to an octal [`String`].
658    ///
659    /// The output is the wrapped [`Float`]'s [`Octal`] output, followed by `#` and the precision.
660    /// Using the `#` format flag prepends `"0o"` to the value, after any sign.
661    ///
662    /// Like the hexadecimal form, this identifies a [`Float`] exactly: the digits are exact because
663    /// the base is a power of two, and the suffix supplies the precision, which the digits alone
664    /// may not determine.
665    ///
666    /// # Worst-case complexity
667    /// $T(n) = O(n)$
668    ///
669    /// $M(n) = O(n)$
670    ///
671    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
672    ///
673    /// # Examples
674    /// ```
675    /// use malachite_base::num::basic::traits::{NaN, One};
676    /// use malachite_float::{ComparableFloatRef, Float};
677    ///
678    /// assert_eq!(format!("{:o}", ComparableFloatRef(&Float::ONE)), "1.0#1");
679    /// assert_eq!(format!("{:#o}", ComparableFloatRef(&Float::ONE)), "0o1.0#1");
680    /// assert_eq!(
681    ///     format!("{:#o}", ComparableFloatRef(&Float::from(1.5))),
682    ///     "0o1.4#2"
683    /// );
684    /// assert_eq!(
685    ///     format!("{:#o}", ComparableFloatRef(&Float::from(255))),
686    ///     "0o377.0#8"
687    /// );
688    /// assert_eq!(format!("{:#o}", ComparableFloatRef(&Float::NAN)), "NaN");
689    /// ```
690    fn fmt(&self, f: &mut Formatter) -> Result {
691        if let x @ Float(Finite { precision, .. }) = &self.0 {
692            if f.alternate() {
693                write!(f, "{x:#o}")?;
694            } else {
695                write!(f, "{x:o}")?;
696            }
697            f.write_char('#')?;
698            write!(f, "{precision}")
699        } else {
700            Octal::fmt(&self.0, f)
701        }
702    }
703}
704
705impl UpperHex for ComparableFloatRef<'_> {
706    /// Converts a [`ComparableFloatRef`] to a hexadecimal [`String`].
707    ///
708    /// The output is the wrapped [`Float`]'s [`UpperHex`] output, followed by `#` and the
709    /// precision. Using the `#` format flag prepends `"0x"` to the value, after any sign.
710    ///
711    /// Like the hexadecimal form, this identifies a [`Float`] exactly: the digits are exact because
712    /// the base is a power of two, and the suffix supplies the precision, which the digits alone
713    /// may not determine.
714    ///
715    /// # Worst-case complexity
716    /// $T(n) = O(n)$
717    ///
718    /// $M(n) = O(n)$
719    ///
720    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
721    ///
722    /// # Examples
723    /// ```
724    /// use malachite_base::num::basic::traits::{NaN, One};
725    /// use malachite_float::{ComparableFloatRef, Float};
726    ///
727    /// assert_eq!(format!("{:X}", ComparableFloatRef(&Float::ONE)), "1.0#1");
728    /// assert_eq!(format!("{:#X}", ComparableFloatRef(&Float::ONE)), "0x1.0#1");
729    /// assert_eq!(
730    ///     format!("{:#X}", ComparableFloatRef(&Float::from(255))),
731    ///     "0xFF.0#8"
732    /// );
733    /// // As for `Float`, the prefix stays lowercase, matching the primitive integers.
734    /// assert_eq!(
735    ///     format!("{:#X}", ComparableFloatRef(&Float::from(-1.5))),
736    ///     "-0x1.8#2"
737    /// );
738    /// assert_eq!(format!("{:#X}", ComparableFloatRef(&Float::NAN)), "NaN");
739    /// ```
740    fn fmt(&self, f: &mut Formatter) -> Result {
741        if let x @ Float(Finite { precision, .. }) = &self.0 {
742            if f.alternate() {
743                write!(f, "{x:#X}")?;
744            } else {
745                write!(f, "{x:X}")?;
746            }
747            f.write_char('#')?;
748            write!(f, "{precision}")
749        } else {
750            UpperHex::fmt(&self.0, f)
751        }
752    }
753}
754
755impl Debug for ComparableFloatRef<'_> {
756    /// Converts a [`ComparableFloatRef`] to a [`String`].
757    ///
758    /// This is the same implementation as for [`Display`].
759    ///
760    /// # Worst-case complexity
761    /// $T(n) = O(n (\log n)^2 \log\log n)$
762    ///
763    /// $M(n) = O(n \log n)$
764    ///
765    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
766    ///
767    /// # Examples
768    /// ```
769    /// use malachite_base::num::basic::traits::One;
770    /// use malachite_base::strings::ToDebugString;
771    /// use malachite_float::{ComparableFloatRef, Float};
772    ///
773    /// assert_eq!(ComparableFloatRef(&Float::ONE).to_debug_string(), "1.0#1");
774    /// assert_eq!(
775    ///     ComparableFloatRef(&Float::from(1.5)).to_debug_string(),
776    ///     "1.5#2"
777    /// );
778    /// ```
779    #[inline]
780    fn fmt(&self, f: &mut Formatter) -> Result {
781        Display::fmt(self, f)
782    }
783}