Skip to content

Commit 2b4bd07

Browse files
committed
float_to_str_bytes_common can now handle exponential notation
1 parent fce7922 commit 2b4bd07

File tree

3 files changed

+77
-17
lines changed

3 files changed

+77
-17
lines changed

src/libstd/num/f32.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,7 @@ impl Float for f32 {
718718
#[inline]
719719
pub fn to_str(num: f32) -> ~str {
720720
let (r, _) = strconv::float_to_str_common(
721-
num, 10u, true, strconv::SignNeg, strconv::DigAll);
721+
num, 10u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
722722
r
723723
}
724724

@@ -732,7 +732,7 @@ pub fn to_str(num: f32) -> ~str {
732732
#[inline]
733733
pub fn to_str_hex(num: f32) -> ~str {
734734
let (r, _) = strconv::float_to_str_common(
735-
num, 16u, true, strconv::SignNeg, strconv::DigAll);
735+
num, 16u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
736736
r
737737
}
738738

@@ -748,7 +748,7 @@ pub fn to_str_hex(num: f32) -> ~str {
748748
#[inline]
749749
pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) {
750750
strconv::float_to_str_common(num, rdx, true,
751-
strconv::SignNeg, strconv::DigAll)
751+
strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false)
752752
}
753753

754754
///
@@ -763,7 +763,7 @@ pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) {
763763
#[inline]
764764
pub fn to_str_exact(num: f32, dig: uint) -> ~str {
765765
let (r, _) = strconv::float_to_str_common(
766-
num, 10u, true, strconv::SignNeg, strconv::DigExact(dig));
766+
num, 10u, true, strconv::SignNeg, strconv::DigExact(dig), strconv::ExpNone, false);
767767
r
768768
}
769769

@@ -779,7 +779,7 @@ pub fn to_str_exact(num: f32, dig: uint) -> ~str {
779779
#[inline]
780780
pub fn to_str_digits(num: f32, dig: uint) -> ~str {
781781
let (r, _) = strconv::float_to_str_common(
782-
num, 10u, true, strconv::SignNeg, strconv::DigMax(dig));
782+
num, 10u, true, strconv::SignNeg, strconv::DigMax(dig), strconv::ExpNone, false);
783783
r
784784
}
785785

@@ -804,7 +804,7 @@ impl num::ToStrRadix for f32 {
804804
#[inline]
805805
fn to_str_radix(&self, rdx: uint) -> ~str {
806806
let (r, special) = strconv::float_to_str_common(
807-
*self, rdx, true, strconv::SignNeg, strconv::DigAll);
807+
*self, rdx, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
808808
if special { fail!("number has a special value, \
809809
try to_str_radix_special() if those are expected") }
810810
r

src/libstd/num/f64.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ impl Float for f64 {
720720
#[inline]
721721
pub fn to_str(num: f64) -> ~str {
722722
let (r, _) = strconv::float_to_str_common(
723-
num, 10u, true, strconv::SignNeg, strconv::DigAll);
723+
num, 10u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
724724
r
725725
}
726726

@@ -734,7 +734,7 @@ pub fn to_str(num: f64) -> ~str {
734734
#[inline]
735735
pub fn to_str_hex(num: f64) -> ~str {
736736
let (r, _) = strconv::float_to_str_common(
737-
num, 16u, true, strconv::SignNeg, strconv::DigAll);
737+
num, 16u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
738738
r
739739
}
740740

@@ -750,7 +750,7 @@ pub fn to_str_hex(num: f64) -> ~str {
750750
#[inline]
751751
pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) {
752752
strconv::float_to_str_common(num, rdx, true,
753-
strconv::SignNeg, strconv::DigAll)
753+
strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false)
754754
}
755755

756756
///
@@ -765,7 +765,7 @@ pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) {
765765
#[inline]
766766
pub fn to_str_exact(num: f64, dig: uint) -> ~str {
767767
let (r, _) = strconv::float_to_str_common(
768-
num, 10u, true, strconv::SignNeg, strconv::DigExact(dig));
768+
num, 10u, true, strconv::SignNeg, strconv::DigExact(dig), strconv::ExpNone, false);
769769
r
770770
}
771771

@@ -781,7 +781,7 @@ pub fn to_str_exact(num: f64, dig: uint) -> ~str {
781781
#[inline]
782782
pub fn to_str_digits(num: f64, dig: uint) -> ~str {
783783
let (r, _) = strconv::float_to_str_common(
784-
num, 10u, true, strconv::SignNeg, strconv::DigMax(dig));
784+
num, 10u, true, strconv::SignNeg, strconv::DigMax(dig), strconv::ExpNone, false);
785785
r
786786
}
787787

@@ -806,7 +806,7 @@ impl num::ToStrRadix for f64 {
806806
#[inline]
807807
fn to_str_radix(&self, rdx: uint) -> ~str {
808808
let (r, special) = strconv::float_to_str_common(
809-
*self, rdx, true, strconv::SignNeg, strconv::DigAll);
809+
*self, rdx, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
810810
if special { fail!("number has a special value, \
811811
try to_str_radix_special() if those are expected") }
812812
r

src/libstd/num/strconv.rs

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,13 @@ pub fn int_to_str_bytes_common<T:NumCast
207207
* # Arguments
208208
* - `num` - The number to convert. Accepts any number that
209209
* implements the numeric traits.
210-
* - `radix` - Base to use. Accepts only the values 2-36.
210+
* - `radix` - Base to use. Accepts only the values 2-36. If the exponential notation
211+
* is used, then this base is only used for the significand. The exponent
212+
* itself always printed using a base of 10.
211213
* - `negative_zero` - Whether to treat the special value `-0` as
212214
* `-0` or as `+0`.
213215
* - `sign` - How to emit the sign. Options are:
214-
* - `SignNone`: No sign at all. Basically emits `abs(num)`.
216+
* - `SignNone`: No sign at all. The exponent sign is also omitted.
215217
* - `SignNeg`: Only `-` on negative values.
216218
* - `SignAll`: Both `+` on positive, and `-` on negative numbers.
217219
* - `digits` - The amount of digits to use for emitting the
@@ -220,6 +222,17 @@ pub fn int_to_str_bytes_common<T:NumCast
220222
* fractions!
221223
* - `DigMax(uint)`: Maximum N digits, truncating any trailing zeros.
222224
* - `DigExact(uint)`: Exactly N digits.
225+
* - `exp_format` - Whether or not to use the exponential (scientific) notation.
226+
* Options are:
227+
* - `ExpNone`: Do not use the exponential notation.
228+
* - `ExpDec`: Use the exponential notation with the exponent having a base of 10,
229+
* and exponent sign being `'e'` or `'E'` depending on the value of
230+
* the `exp_upper` argument. E.g. the number 1000 would be printed as 1e3.
231+
* - `ExpBin`: Use the exponential notation with the exponent having a base of 2,
232+
* and exponent sign being `'p'` or `'P'` depending on the value of
233+
* the `exp_upper` argument. E.g. the number 8 would be printed as 1p3.
234+
* - `exp_capital` - Whether or not to use a capital letter for the exponent sign, if
235+
* exponential notation is desired.
223236
*
224237
* # Return value
225238
* A tuple containing the byte vector, and a boolean flag indicating
@@ -229,12 +242,26 @@ pub fn int_to_str_bytes_common<T:NumCast
229242
*
230243
* # Failure
231244
* - Fails if `radix` < 2 or `radix` > 36.
245+
* - Fails if `radix` > 14 and `exp_format` is `ExpDec` due to conflict
246+
* between digit and exponent sign `'e'`.
247+
* - Fails if `radix` > 25 and `exp_format` is `ExpBin` due to conflict
248+
* between digit and exponent sign `'p'`.
232249
*/
233250
pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+Round+
234251
Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
235252
num: T, radix: uint, negative_zero: bool,
236-
sign: SignFormat, digits: SignificantDigits) -> (~[u8], bool) {
253+
sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_upper: bool
254+
) -> (~[u8], bool) {
237255
assert!(2 <= radix && radix <= 36);
256+
match exp_format {
257+
ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e'
258+
=> fail!("float_to_str_bytes_common: radix {} incompatible with \
259+
use of 'e' as decimal exponent", radix),
260+
ExpBin if radix >= DIGIT_P_RADIX // binary exponent 'p'
261+
=> fail!("float_to_str_bytes_common: radix {} incompatible with \
262+
use of 'p' as binary exponent", radix),
263+
_ => ()
264+
}
238265

239266
let _0: T = Zero::zero();
240267
let _1: T = One::one();
@@ -260,6 +287,23 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+Round+
260287
let mut buf: ~[u8] = ~[];
261288
let radix_gen: T = cast(radix as int).unwrap();
262289

290+
let (num, exp) = match exp_format {
291+
ExpNone => (num, 0i32),
292+
ExpDec | ExpBin => {
293+
if num == _0 {
294+
(num, 0i32)
295+
} else {
296+
let (exp, exp_base) = match exp_format {
297+
ExpDec => (num.abs().log10().floor(), cast::<f64, T>(10.0f64).unwrap()),
298+
ExpBin => (num.abs().log2().floor(), cast::<f64, T>(2.0f64).unwrap()),
299+
ExpNone => unreachable!()
300+
};
301+
302+
(num / exp_base.powf(&exp), cast::<T, i32>(exp).unwrap())
303+
}
304+
}
305+
};
306+
263307
// First emit the non-fractional part, looping at least once to make
264308
// sure at least a `0` gets emitted.
265309
let mut deccum = num.trunc();
@@ -413,6 +457,21 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+Round+
413457
}
414458
}
415459

460+
match exp_format {
461+
ExpNone => (),
462+
_ => {
463+
buf.push(match exp_format {
464+
ExpDec if exp_upper => 'E',
465+
ExpDec if !exp_upper => 'e',
466+
ExpBin if exp_upper => 'P',
467+
ExpBin if !exp_upper => 'p',
468+
_ => unreachable!()
469+
} as u8);
470+
471+
int_to_str_bytes_common(exp, 10, sign, |c| buf.push(c));
472+
}
473+
}
474+
416475
(buf, false)
417476
}
418477

@@ -424,9 +483,10 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+Round+
424483
pub fn float_to_str_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Float+Round+
425484
Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
426485
num: T, radix: uint, negative_zero: bool,
427-
sign: SignFormat, digits: SignificantDigits) -> (~str, bool) {
486+
sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_capital: bool
487+
) -> (~str, bool) {
428488
let (bytes, special) = float_to_str_bytes_common(num, radix,
429-
negative_zero, sign, digits);
489+
negative_zero, sign, digits, exp_format, exp_capital);
430490
(str::from_utf8_owned(bytes).unwrap(), special)
431491
}
432492

0 commit comments

Comments
 (0)