Skip to content

Commit dc3a300

Browse files
committed
Unify format_float_as_exponent to clarify
1 parent 249f121 commit dc3a300

File tree

3 files changed

+26
-40
lines changed

3 files changed

+26
-40
lines changed

common/src/float_ops.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,23 @@ pub fn is_integer(v: f64) -> bool {
8383
(v - v.round()).abs() < std::f64::EPSILON
8484
}
8585

86+
// Formats floats into Python style exponent notation, by first formatting in Rust style
87+
// exponent notation (`1.0000e0`), then convert to Python style (`1.0000e+00`).
88+
pub fn format_float_as_exponent(precision: usize, magnitude: f64) -> String {
89+
if magnitude.is_nan() {
90+
return "nan".to_string();
91+
}
92+
if magnitude.is_infinite() {
93+
return "inf".to_string();
94+
}
95+
96+
let r_exp = format!("{:.*e}", precision, magnitude);
97+
let mut parts = r_exp.splitn(2, 'e');
98+
let base = parts.next().unwrap();
99+
let exponent = parts.next().unwrap().parse::<i64>().unwrap();
100+
format!("{}e{:+#03}", base, exponent)
101+
}
102+
86103
pub fn to_string(value: f64) -> String {
87104
let lit = format!("{:e}", value);
88105
if let Some(position) = lit.find('e') {

vm/src/cformat.rs

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::builtins::{float, int, pystr, tuple};
2+
use crate::common::float_ops;
23
/// Implementation of Printf-Style string formatting
34
/// [https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting]
45
use crate::format::get_num_digits;
@@ -242,24 +243,6 @@ impl CFormatSpec {
242243
}
243244
}
244245

245-
fn normalize_float(&self, num: f64) -> (f64, i32) {
246-
let mut fraction = num;
247-
let mut exponent = 0;
248-
loop {
249-
if fraction >= 10.0 {
250-
fraction /= 10.0;
251-
exponent += 1;
252-
} else if fraction < 1.0 && fraction > 0.0 {
253-
fraction *= 10.0;
254-
exponent -= 1;
255-
} else {
256-
break;
257-
}
258-
}
259-
260-
(fraction, exponent)
261-
}
262-
263246
pub(crate) fn format_float(&self, num: f64) -> Result<String, String> {
264247
let sign_string = if num.is_sign_positive() {
265248
self.flags.sign_string()
@@ -281,8 +264,8 @@ impl CFormatSpec {
281264
Some(CFormatQuantity::Amount(p)) => p,
282265
_ => 6,
283266
};
284-
let (fraction, exponent) = self.normalize_float(num.abs());
285-
Ok(format!("{:.*}e{:+03}", precision, fraction, exponent))
267+
let magnitude = num.abs();
268+
Ok(float_ops::format_float_as_exponent(precision, magnitude))
286269
}
287270
CFormatType::Float(CFloatType::General(_)) => {
288271
Err("Not yet implemented for %g and %G".to_owned())

vm/src/format.rs

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -277,16 +277,6 @@ fn parse_format_spec(text: &str) -> Result<FormatSpec, &'static str> {
277277
})
278278
}
279279

280-
// Formats floats into Python style exponent notation, by first formatting in Rust style
281-
// exponent notation (`1.0000e0`), then convert to Python style (`1.0000e+00`).
282-
fn format_float_as_exponent(precision: usize, magnitude: f64, separator: &str) -> String {
283-
let r_exp = format!("{:.*e}", precision, magnitude);
284-
let mut parts = r_exp.splitn(2, 'e');
285-
let base = parts.next().unwrap();
286-
let exponent = parts.next().unwrap().parse::<i64>().unwrap();
287-
format!("{}{}+{:02}", base, separator, exponent)
288-
}
289-
290280
impl FormatSpec {
291281
pub(crate) fn parse(text: &str) -> Result<FormatSpec, &'static str> {
292282
parse_format_spec(text)
@@ -385,16 +375,12 @@ impl FormatSpec {
385375
Some(FormatType::GeneralFormatLower) => {
386376
Err("Format code 'g' for object of type 'float' not implemented yet")
387377
}
388-
Some(FormatType::ExponentUpper) => match magnitude {
389-
magnitude if magnitude.is_nan() => Ok("NAN".to_owned()),
390-
magnitude if magnitude.is_infinite() => Ok("INF".to_owned()),
391-
_ => Ok(format_float_as_exponent(precision, magnitude, "E")),
392-
},
393-
Some(FormatType::ExponentLower) => match magnitude {
394-
magnitude if magnitude.is_nan() => Ok("nan".to_owned()),
395-
magnitude if magnitude.is_infinite() => Ok("inf".to_owned()),
396-
_ => Ok(format_float_as_exponent(precision, magnitude, "e")),
397-
},
378+
Some(FormatType::ExponentUpper) => {
379+
Ok(float_ops::format_float_as_exponent(precision, magnitude).to_uppercase())
380+
}
381+
Some(FormatType::ExponentLower) => {
382+
Ok(float_ops::format_float_as_exponent(precision, magnitude).to_lowercase())
383+
}
398384
Some(FormatType::Percentage) => match magnitude {
399385
magnitude if magnitude.is_nan() => Ok("nan%".to_owned()),
400386
magnitude if magnitude.is_infinite() => Ok("inf%".to_owned()),

0 commit comments

Comments
 (0)