mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Merge pull request #2316 from ChJR/feature/format_float
Unify float formatting
This commit is contained in:
5 files changed
+276
-74
No files matched your search
@@ -83,6 +83,96 @@ pub fn is_integer(v: f64) -> bool {
|
||||
(v - v.round()).abs() < std::f64::EPSILON
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Case {
|
||||
Lower,
|
||||
Upper,
|
||||
}
|
||||
|
||||
fn format_nan(case: Case) -> String {
|
||||
let nan = match case {
|
||||
Case::Lower => "nan",
|
||||
Case::Upper => "NAN",
|
||||
};
|
||||
|
||||
nan.to_string()
|
||||
}
|
||||
|
||||
fn format_inf(case: Case) -> String {
|
||||
let inf = match case {
|
||||
Case::Lower => "inf",
|
||||
Case::Upper => "INF",
|
||||
};
|
||||
|
||||
inf.to_string()
|
||||
}
|
||||
|
||||
pub fn format_fixed(precision: usize, magnitude: f64, case: Case) -> String {
|
||||
match magnitude {
|
||||
magnitude if magnitude.is_finite() => format!("{:.*}", precision, magnitude),
|
||||
magnitude if magnitude.is_nan() => format_nan(case),
|
||||
magnitude if magnitude.is_infinite() => format_inf(case),
|
||||
_ => "".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
// Formats floats into Python style exponent notation, by first formatting in Rust style
|
||||
// exponent notation (`1.0000e0`), then convert to Python style (`1.0000e+00`).
|
||||
pub fn format_exponent(precision: usize, magnitude: f64, case: Case) -> String {
|
||||
match magnitude {
|
||||
magnitude if magnitude.is_finite() => {
|
||||
let r_exp = format!("{:.*e}", precision, magnitude);
|
||||
let mut parts = r_exp.splitn(2, 'e');
|
||||
let base = parts.next().unwrap();
|
||||
let exponent = parts.next().unwrap().parse::<i64>().unwrap();
|
||||
let e = match case {
|
||||
Case::Lower => 'e',
|
||||
Case::Upper => 'E',
|
||||
};
|
||||
format!("{}{}{:+#03}", base, e, exponent)
|
||||
}
|
||||
magnitude if magnitude.is_nan() => format_nan(case),
|
||||
magnitude if magnitude.is_infinite() => format_inf(case),
|
||||
_ => "".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_trailing_zeros(s: String) -> String {
|
||||
let mut s = s;
|
||||
while s.ends_with('0') || s.ends_with('.') {
|
||||
s.truncate(s.len() - 1);
|
||||
}
|
||||
|
||||
s
|
||||
}
|
||||
|
||||
pub fn format_general(precision: usize, magnitude: f64, case: Case) -> String {
|
||||
match magnitude {
|
||||
magnitude if magnitude.is_finite() => {
|
||||
let r_exp = format!("{:.*e}", precision.saturating_sub(1), magnitude);
|
||||
let mut parts = r_exp.splitn(2, 'e');
|
||||
let base = parts.next().unwrap();
|
||||
let exponent = parts.next().unwrap().parse::<i64>().unwrap();
|
||||
if exponent < -4 || exponent >= (precision as i64) {
|
||||
let e = match case {
|
||||
Case::Lower => 'e',
|
||||
Case::Upper => 'E',
|
||||
};
|
||||
|
||||
let base = remove_trailing_zeros(format!("{:.*}", precision + 1, base));
|
||||
format!("{}{}{:+#03}", base, e, exponent)
|
||||
} else {
|
||||
let precision = (precision as i64) - 1 - exponent;
|
||||
let precision = precision as usize;
|
||||
remove_trailing_zeros(format!("{:.*}", precision, magnitude))
|
||||
}
|
||||
}
|
||||
magnitude if magnitude.is_nan() => format_nan(case),
|
||||
magnitude if magnitude.is_infinite() => format_inf(case),
|
||||
_ => "".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string(value: f64) -> String {
|
||||
let lit = format!("{:e}", value);
|
||||
if let Some(position) = lit.find('e') {
|
||||
|
||||
@@ -232,6 +232,73 @@ assert "%e" % 0 == '0.000000e+00'
|
||||
assert "%e" % 0.1 == '1.000000e-01'
|
||||
assert "%e" % 10 == '1.000000e+01'
|
||||
assert "%.10e" % 1.2345678901234567890 == '1.2345678901e+00'
|
||||
assert '%e' % float('nan') == 'nan'
|
||||
assert '%e' % float('-nan') == 'nan'
|
||||
assert '%E' % float('nan') == 'NAN'
|
||||
assert '%e' % float('inf') == 'inf'
|
||||
assert '%e' % float('-inf') == '-inf'
|
||||
assert '%E' % float('inf') == 'INF'
|
||||
assert "%g" % 123456.78901234567890 == '123457'
|
||||
assert "%.0g" % 123456.78901234567890 == '1e+05'
|
||||
assert "%.1g" % 123456.78901234567890 == '1e+05'
|
||||
assert "%.2g" % 123456.78901234567890 == '1.2e+05'
|
||||
assert "%g" % 1234567.8901234567890 == '1.23457e+06'
|
||||
assert "%.0g" % 1234567.8901234567890 == '1e+06'
|
||||
assert "%.1g" % 1234567.8901234567890 == '1e+06'
|
||||
assert "%.2g" % 1234567.8901234567890 == '1.2e+06'
|
||||
assert "%.3g" % 1234567.8901234567890 == '1.23e+06'
|
||||
assert "%.5g" % 1234567.8901234567890 == '1.2346e+06'
|
||||
assert "%.6g" % 1234567.8901234567890 == '1.23457e+06'
|
||||
assert "%.7g" % 1234567.8901234567890 == '1234568'
|
||||
assert "%.8g" % 1234567.8901234567890 == '1234567.9'
|
||||
assert "%G" % 123456.78901234567890 == '123457'
|
||||
assert "%.0G" % 123456.78901234567890 == '1E+05'
|
||||
assert "%.1G" % 123456.78901234567890 == '1E+05'
|
||||
assert "%.2G" % 123456.78901234567890 == '1.2E+05'
|
||||
assert "%G" % 1234567.8901234567890 == '1.23457E+06'
|
||||
assert "%.0G" % 1234567.8901234567890 == '1E+06'
|
||||
assert "%.1G" % 1234567.8901234567890 == '1E+06'
|
||||
assert "%.2G" % 1234567.8901234567890 == '1.2E+06'
|
||||
assert "%.3G" % 1234567.8901234567890 == '1.23E+06'
|
||||
assert "%.5G" % 1234567.8901234567890 == '1.2346E+06'
|
||||
assert "%.6G" % 1234567.8901234567890 == '1.23457E+06'
|
||||
assert "%.7G" % 1234567.8901234567890 == '1234568'
|
||||
assert "%.8G" % 1234567.8901234567890 == '1234567.9'
|
||||
assert '%g' % 0.12345678901234567890 == '0.123457'
|
||||
assert '%g' % 0.12345678901234567890e-1 == '0.0123457'
|
||||
assert '%g' % 0.12345678901234567890e-2 == '0.00123457'
|
||||
assert '%g' % 0.12345678901234567890e-3 == '0.000123457'
|
||||
assert '%g' % 0.12345678901234567890e-4 == '1.23457e-05'
|
||||
assert '%g' % 0.12345678901234567890e-5 == '1.23457e-06'
|
||||
assert '%.6g' % 0.12345678901234567890e-5 == '1.23457e-06'
|
||||
assert '%.10g' % 0.12345678901234567890e-5 == '1.23456789e-06'
|
||||
assert '%.20g' % 0.12345678901234567890e-5 == '1.2345678901234567384e-06'
|
||||
assert '%G' % 0.12345678901234567890 == '0.123457'
|
||||
assert '%G' % 0.12345678901234567890E-1 == '0.0123457'
|
||||
assert '%G' % 0.12345678901234567890E-2 == '0.00123457'
|
||||
assert '%G' % 0.12345678901234567890E-3 == '0.000123457'
|
||||
assert '%G' % 0.12345678901234567890E-4 == '1.23457E-05'
|
||||
assert '%G' % 0.12345678901234567890E-5 == '1.23457E-06'
|
||||
assert '%.6G' % 0.12345678901234567890E-5 == '1.23457E-06'
|
||||
assert '%.10G' % 0.12345678901234567890E-5 == '1.23456789E-06'
|
||||
assert '%.20G' % 0.12345678901234567890E-5 == '1.2345678901234567384E-06'
|
||||
assert '%g' % float('nan') == 'nan'
|
||||
assert '%g' % float('-nan') == 'nan'
|
||||
assert '%G' % float('nan') == 'NAN'
|
||||
assert '%g' % float('inf') == 'inf'
|
||||
assert '%g' % float('-inf') == '-inf'
|
||||
assert '%G' % float('inf') == 'INF'
|
||||
assert "%.0g" % 1.020e-13 == '1e-13'
|
||||
assert "%.0g" % 1.020e-13 == '1e-13'
|
||||
assert "%.1g" % 1.020e-13 == '1e-13'
|
||||
assert "%.2g" % 1.020e-13 == '1e-13'
|
||||
assert "%.3g" % 1.020e-13 == '1.02e-13'
|
||||
assert "%.4g" % 1.020e-13 == '1.02e-13'
|
||||
assert "%.5g" % 1.020e-13 == '1.02e-13'
|
||||
assert "%.6g" % 1.020e-13 == '1.02e-13'
|
||||
assert "%.7g" % 1.020e-13 == '1.02e-13'
|
||||
assert "%g" % 1.020e-13 == '1.02e-13'
|
||||
assert "%g" % 1.020e-4 == '0.000102'
|
||||
|
||||
assert_raises(TypeError, lambda: "My name is %s and I'm %(age)d years old" % ("Foo", 25), _msg='format requires a mapping')
|
||||
assert_raises(TypeError, lambda: "My name is %(name)s" % "Foo", _msg='format requires a mapping')
|
||||
@@ -477,6 +544,68 @@ assert '{:e}'.format(float('inf')) == 'inf'
|
||||
assert '{:e}'.format(float('-inf')) == '-inf'
|
||||
assert '{:E}'.format(float('inf')) == 'INF'
|
||||
|
||||
# Test g & G formatting
|
||||
assert '{:g}'.format(123456.78901234567890) == '123457'
|
||||
assert '{:.0g}'.format(123456.78901234567890) == '1e+05'
|
||||
assert '{:.1g}'.format(123456.78901234567890) == '1e+05'
|
||||
assert '{:.2g}'.format(123456.78901234567890) == '1.2e+05'
|
||||
assert '{:g}'.format(1234567.8901234567890) == '1.23457e+06'
|
||||
assert '{:.0g}'.format(1234567.8901234567890) == '1e+06'
|
||||
assert '{:.1g}'.format(1234567.8901234567890) == '1e+06'
|
||||
assert '{:.2g}'.format(1234567.8901234567890) == '1.2e+06'
|
||||
assert '{:.3g}'.format(1234567.8901234567890) == '1.23e+06'
|
||||
assert '{:.5g}'.format(1234567.8901234567890) == '1.2346e+06'
|
||||
assert '{:.6g}'.format(1234567.8901234567890) == '1.23457e+06'
|
||||
assert '{:.7g}'.format(1234567.8901234567890) == '1234568'
|
||||
assert '{:.8g}'.format(1234567.8901234567890) == '1234567.9'
|
||||
assert '{:G}'.format(123456.78901234567890) == '123457'
|
||||
assert '{:.0G}'.format(123456.78901234567890) == '1E+05'
|
||||
assert '{:.1G}'.format(123456.78901234567890) == '1E+05'
|
||||
assert '{:.2G}'.format(123456.78901234567890) == '1.2E+05'
|
||||
assert '{:G}'.format(1234567.8901234567890) == '1.23457E+06'
|
||||
assert '{:.0G}'.format(1234567.8901234567890) == '1E+06'
|
||||
assert '{:.1G}'.format(1234567.8901234567890) == '1E+06'
|
||||
assert '{:.2G}'.format(1234567.8901234567890) == '1.2E+06'
|
||||
assert '{:.3G}'.format(1234567.8901234567890) == '1.23E+06'
|
||||
assert '{:.5G}'.format(1234567.8901234567890) == '1.2346E+06'
|
||||
assert '{:.6G}'.format(1234567.8901234567890) == '1.23457E+06'
|
||||
assert '{:.7G}'.format(1234567.8901234567890) == '1234568'
|
||||
assert '{:.8G}'.format(1234567.8901234567890) == '1234567.9'
|
||||
assert '{:g}'.format(0.12345678901234567890) == '0.123457'
|
||||
assert '{:g}'.format(0.12345678901234567890e-1) == '0.0123457'
|
||||
assert '{:g}'.format(0.12345678901234567890e-2) == '0.00123457'
|
||||
assert '{:g}'.format(0.12345678901234567890e-3) == '0.000123457'
|
||||
assert '{:g}'.format(0.12345678901234567890e-4) == '1.23457e-05'
|
||||
assert '{:g}'.format(0.12345678901234567890e-5) == '1.23457e-06'
|
||||
assert '{:.6g}'.format(0.12345678901234567890e-5) == '1.23457e-06'
|
||||
assert '{:.10g}'.format(0.12345678901234567890e-5) == '1.23456789e-06'
|
||||
assert '{:.20g}'.format(0.12345678901234567890e-5) == '1.2345678901234567384e-06'
|
||||
assert '{:G}'.format(0.12345678901234567890) == '0.123457'
|
||||
assert '{:G}'.format(0.12345678901234567890E-1) == '0.0123457'
|
||||
assert '{:G}'.format(0.12345678901234567890E-2) == '0.00123457'
|
||||
assert '{:G}'.format(0.12345678901234567890E-3) == '0.000123457'
|
||||
assert '{:G}'.format(0.12345678901234567890E-4) == '1.23457E-05'
|
||||
assert '{:G}'.format(0.12345678901234567890E-5) == '1.23457E-06'
|
||||
assert '{:.6G}'.format(0.12345678901234567890E-5) == '1.23457E-06'
|
||||
assert '{:.10G}'.format(0.12345678901234567890E-5) == '1.23456789E-06'
|
||||
assert '{:.20G}'.format(0.12345678901234567890E-5) == '1.2345678901234567384E-06'
|
||||
assert '{:g}'.format(float('nan')) == 'nan'
|
||||
assert '{:g}'.format(float('-nan')) == 'nan'
|
||||
assert '{:G}'.format(float('nan')) == 'NAN'
|
||||
assert '{:g}'.format(float('inf')) == 'inf'
|
||||
assert '{:g}'.format(float('-inf')) == '-inf'
|
||||
assert '{:G}'.format(float('inf')) == 'INF'
|
||||
assert '{:.0g}'.format(1.020e-13) == '1e-13'
|
||||
assert '{:.0g}'.format(1.020e-13) == '1e-13'
|
||||
assert '{:.1g}'.format(1.020e-13) == '1e-13'
|
||||
assert '{:.2g}'.format(1.020e-13) == '1e-13'
|
||||
assert '{:.3g}'.format(1.020e-13) == '1.02e-13'
|
||||
assert '{:.4g}'.format(1.020e-13) == '1.02e-13'
|
||||
assert '{:.5g}'.format(1.020e-13) == '1.02e-13'
|
||||
assert '{:.6g}'.format(1.020e-13) == '1.02e-13'
|
||||
assert '{:.7g}'.format(1.020e-13) == '1.02e-13'
|
||||
assert '{:g}'.format(1.020e-13) == '1.02e-13'
|
||||
assert "{:g}".format(1.020e-4) == '0.000102'
|
||||
|
||||
# remove*fix test
|
||||
def test_removeprefix():
|
||||
|
||||
@@ -180,7 +180,7 @@ impl PyIter for PyStrReverseIterator {
|
||||
break;
|
||||
}
|
||||
}
|
||||
start.unwrap_or(end - 4)
|
||||
start.unwrap_or_else(|| end.saturating_sub(4))
|
||||
};
|
||||
|
||||
let stored = zelf.position.swap(start);
|
||||
|
||||
+24
-41
@@ -4,6 +4,7 @@ use crate::builtins::float::{try_bigint, IntoPyFloat, PyFloat};
|
||||
use crate::builtins::int::{self, PyInt};
|
||||
use crate::builtins::pystr::PyStr;
|
||||
use crate::builtins::{memory::try_buffer_from_object, tuple, PyBytes};
|
||||
use crate::common::float_ops;
|
||||
use crate::pyobject::{
|
||||
BorrowValue, ItemProtocol, PyObjectRef, PyResult, TryFromObject, TypeProtocol,
|
||||
};
|
||||
@@ -76,7 +77,7 @@ enum CNumberType {
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum CFloatType {
|
||||
Exponent(CFormatCase),
|
||||
PointDecimal,
|
||||
PointDecimal(CFormatCase),
|
||||
General(CFormatCase),
|
||||
}
|
||||
|
||||
@@ -292,61 +293,43 @@ impl CFormatSpec {
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_float(&self, num: f64) -> (f64, i32) {
|
||||
let mut fraction = num;
|
||||
let mut exponent = 0;
|
||||
loop {
|
||||
if fraction >= 10.0 {
|
||||
fraction /= 10.0;
|
||||
exponent += 1;
|
||||
} else if fraction < 1.0 && fraction > 0.0 {
|
||||
fraction *= 10.0;
|
||||
exponent -= 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
(fraction, exponent)
|
||||
}
|
||||
|
||||
pub(crate) fn format_float(&self, num: f64) -> String {
|
||||
let sign_string = if num.is_sign_positive() {
|
||||
self.flags.sign_string()
|
||||
} else {
|
||||
let sign_string = if num.is_sign_negative() && !num.is_nan() {
|
||||
"-"
|
||||
} else {
|
||||
self.flags.sign_string()
|
||||
};
|
||||
|
||||
let precision = match self.precision {
|
||||
Some(CFormatQuantity::Amount(p)) => p,
|
||||
_ => 6,
|
||||
};
|
||||
|
||||
let magnitude_string = match &self.format_type {
|
||||
CFormatType::Float(CFloatType::PointDecimal) => {
|
||||
CFormatType::Float(CFloatType::PointDecimal(case)) => {
|
||||
let case = match case {
|
||||
CFormatCase::Lowercase => float_ops::Case::Lower,
|
||||
CFormatCase::Uppercase => float_ops::Case::Upper,
|
||||
};
|
||||
let magnitude = num.abs();
|
||||
format!("{:.*}", precision, magnitude)
|
||||
float_ops::format_fixed(precision, magnitude, case)
|
||||
}
|
||||
CFormatType::Float(CFloatType::Exponent(case)) => {
|
||||
let (fraction, exponent) = self.normalize_float(num.abs());
|
||||
let case = match case {
|
||||
CFormatCase::Lowercase => 'e',
|
||||
CFormatCase::Uppercase => 'E',
|
||||
CFormatCase::Lowercase => float_ops::Case::Lower,
|
||||
CFormatCase::Uppercase => float_ops::Case::Upper,
|
||||
};
|
||||
format!("{:.*}{}{:+03}", precision, fraction, case, exponent)
|
||||
let magnitude = num.abs();
|
||||
float_ops::format_exponent(precision, magnitude, case)
|
||||
}
|
||||
CFormatType::Float(CFloatType::General(case)) => {
|
||||
let precision = if precision == 0 { 1 } else { precision };
|
||||
let (fraction, exponent) = self.normalize_float(num.abs());
|
||||
if exponent < -4 || exponent >= (precision as i32) {
|
||||
let case = match case {
|
||||
CFormatCase::Lowercase => 'e',
|
||||
CFormatCase::Uppercase => 'E',
|
||||
};
|
||||
format!("{}{}{:+03}", fraction, case, exponent)
|
||||
} else {
|
||||
let magnitude = num.abs();
|
||||
format!("{}", magnitude)
|
||||
}
|
||||
let case = match case {
|
||||
CFormatCase::Lowercase => float_ops::Case::Lower,
|
||||
CFormatCase::Uppercase => float_ops::Case::Upper,
|
||||
};
|
||||
let magnitude = num.abs();
|
||||
float_ops::format_general(precision, magnitude, case)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
@@ -1053,8 +1036,8 @@ where
|
||||
'X' => CFormatType::Number(Hex(Uppercase)),
|
||||
'e' => CFormatType::Float(Exponent(Lowercase)),
|
||||
'E' => CFormatType::Float(Exponent(Uppercase)),
|
||||
'f' => CFormatType::Float(PointDecimal),
|
||||
'F' => CFormatType::Float(PointDecimal),
|
||||
'f' => CFormatType::Float(PointDecimal(Lowercase)),
|
||||
'F' => CFormatType::Float(PointDecimal(Uppercase)),
|
||||
'g' => CFormatType::Float(General(Lowercase)),
|
||||
'G' => CFormatType::Float(General(Uppercase)),
|
||||
'c' => CFormatType::Character,
|
||||
|
||||
+32
-32
@@ -277,16 +277,6 @@ fn parse_format_spec(text: &str) -> Result<FormatSpec, &'static str> {
|
||||
})
|
||||
}
|
||||
|
||||
// Formats floats into Python style exponent notation, by first formatting in Rust style
|
||||
// exponent notation (`1.0000e0`), then convert to Python style (`1.0000e+00`).
|
||||
fn format_float_as_exponent(precision: usize, magnitude: f64, separator: &str) -> String {
|
||||
let r_exp = format!("{:.*e}", precision, magnitude);
|
||||
let mut parts = r_exp.splitn(2, 'e');
|
||||
let base = parts.next().unwrap();
|
||||
let exponent = parts.next().unwrap().parse::<i64>().unwrap();
|
||||
format!("{}{}+{:02}", base, separator, exponent)
|
||||
}
|
||||
|
||||
impl FormatSpec {
|
||||
pub(crate) fn parse(text: &str) -> Result<FormatSpec, &'static str> {
|
||||
parse_format_spec(text)
|
||||
@@ -357,16 +347,16 @@ impl FormatSpec {
|
||||
let precision = self.precision.unwrap_or(6);
|
||||
let magnitude = num.abs();
|
||||
let raw_magnitude_string_result: Result<String, &'static str> = match self.format_type {
|
||||
Some(FormatType::FixedPointUpper) => match magnitude {
|
||||
magnitude if magnitude.is_nan() => Ok("NAN".to_owned()),
|
||||
magnitude if magnitude.is_infinite() => Ok("INF".to_owned()),
|
||||
_ => Ok(format!("{:.*}", precision, magnitude)),
|
||||
},
|
||||
Some(FormatType::FixedPointLower) => match magnitude {
|
||||
magnitude if magnitude.is_nan() => Ok("nan".to_owned()),
|
||||
magnitude if magnitude.is_infinite() => Ok("inf".to_owned()),
|
||||
_ => Ok(format!("{:.*}", precision, magnitude)),
|
||||
},
|
||||
Some(FormatType::FixedPointUpper) => Ok(float_ops::format_fixed(
|
||||
precision,
|
||||
magnitude,
|
||||
float_ops::Case::Upper,
|
||||
)),
|
||||
Some(FormatType::FixedPointLower) => Ok(float_ops::format_fixed(
|
||||
precision,
|
||||
magnitude,
|
||||
float_ops::Case::Lower,
|
||||
)),
|
||||
Some(FormatType::Decimal) => Err("Unknown format code 'd' for object of type 'float'"),
|
||||
Some(FormatType::Binary) => Err("Unknown format code 'b' for object of type 'float'"),
|
||||
Some(FormatType::Octal) => Err("Unknown format code 'o' for object of type 'float'"),
|
||||
@@ -380,21 +370,31 @@ impl FormatSpec {
|
||||
Err("Format code 'n' for object of type 'float' not implemented yet")
|
||||
}
|
||||
Some(FormatType::GeneralFormatUpper) => {
|
||||
Err("Format code 'G' for object of type 'float' not implemented yet")
|
||||
let precision = if precision == 0 { 1 } else { precision };
|
||||
Ok(float_ops::format_general(
|
||||
precision,
|
||||
magnitude,
|
||||
float_ops::Case::Upper,
|
||||
))
|
||||
}
|
||||
Some(FormatType::GeneralFormatLower) => {
|
||||
Err("Format code 'g' for object of type 'float' not implemented yet")
|
||||
let precision = if precision == 0 { 1 } else { precision };
|
||||
Ok(float_ops::format_general(
|
||||
precision,
|
||||
magnitude,
|
||||
float_ops::Case::Lower,
|
||||
))
|
||||
}
|
||||
Some(FormatType::ExponentUpper) => match magnitude {
|
||||
magnitude if magnitude.is_nan() => Ok("NAN".to_owned()),
|
||||
magnitude if magnitude.is_infinite() => Ok("INF".to_owned()),
|
||||
_ => Ok(format_float_as_exponent(precision, magnitude, "E")),
|
||||
},
|
||||
Some(FormatType::ExponentLower) => match magnitude {
|
||||
magnitude if magnitude.is_nan() => Ok("nan".to_owned()),
|
||||
magnitude if magnitude.is_infinite() => Ok("inf".to_owned()),
|
||||
_ => Ok(format_float_as_exponent(precision, magnitude, "e")),
|
||||
},
|
||||
Some(FormatType::ExponentUpper) => Ok(float_ops::format_exponent(
|
||||
precision,
|
||||
magnitude,
|
||||
float_ops::Case::Upper,
|
||||
)),
|
||||
Some(FormatType::ExponentLower) => Ok(float_ops::format_exponent(
|
||||
precision,
|
||||
magnitude,
|
||||
float_ops::Case::Lower,
|
||||
)),
|
||||
Some(FormatType::Percentage) => match magnitude {
|
||||
magnitude if magnitude.is_nan() => Ok("nan%".to_owned()),
|
||||
magnitude if magnitude.is_infinite() => Ok("inf%".to_owned()),
|
||||
|
||||
Reference in new issue
Block a user