diff options
| author | SiegeLord <slabode@aim.com> | 2014-01-16 18:24:03 -0500 |
|---|---|---|
| committer | SiegeLord <slabode@aim.com> | 2014-01-22 20:32:40 -0500 |
| commit | 2b4bd0780bb98f4171dd6464a4f01065b8d85ffd (patch) | |
| tree | 85887b4fd5a178eda845b44343fa84cb46745fad /src/libstd | |
| parent | fce792249e72a181f2ad52413b25b1db643c371f (diff) | |
| download | rust-2b4bd0780bb98f4171dd6464a4f01065b8d85ffd.tar.gz rust-2b4bd0780bb98f4171dd6464a4f01065b8d85ffd.zip | |
float_to_str_bytes_common can now handle exponential notation
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/num/f32.rs | 12 | ||||
| -rw-r--r-- | src/libstd/num/f64.rs | 12 | ||||
| -rw-r--r-- | src/libstd/num/strconv.rs | 70 |
3 files changed, 77 insertions, 17 deletions
diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 5b0c75ef174..e95ad7ca7f5 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -718,7 +718,7 @@ impl Float for f32 { #[inline] pub fn to_str(num: f32) -> ~str { let (r, _) = strconv::float_to_str_common( - num, 10u, true, strconv::SignNeg, strconv::DigAll); + num, 10u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false); r } @@ -732,7 +732,7 @@ pub fn to_str(num: f32) -> ~str { #[inline] pub fn to_str_hex(num: f32) -> ~str { let (r, _) = strconv::float_to_str_common( - num, 16u, true, strconv::SignNeg, strconv::DigAll); + num, 16u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false); r } @@ -748,7 +748,7 @@ pub fn to_str_hex(num: f32) -> ~str { #[inline] pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) { strconv::float_to_str_common(num, rdx, true, - strconv::SignNeg, strconv::DigAll) + strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false) } /// @@ -763,7 +763,7 @@ pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) { #[inline] pub fn to_str_exact(num: f32, dig: uint) -> ~str { let (r, _) = strconv::float_to_str_common( - num, 10u, true, strconv::SignNeg, strconv::DigExact(dig)); + num, 10u, true, strconv::SignNeg, strconv::DigExact(dig), strconv::ExpNone, false); r } @@ -779,7 +779,7 @@ pub fn to_str_exact(num: f32, dig: uint) -> ~str { #[inline] pub fn to_str_digits(num: f32, dig: uint) -> ~str { let (r, _) = strconv::float_to_str_common( - num, 10u, true, strconv::SignNeg, strconv::DigMax(dig)); + num, 10u, true, strconv::SignNeg, strconv::DigMax(dig), strconv::ExpNone, false); r } @@ -804,7 +804,7 @@ impl num::ToStrRadix for f32 { #[inline] fn to_str_radix(&self, rdx: uint) -> ~str { let (r, special) = strconv::float_to_str_common( - *self, rdx, true, strconv::SignNeg, strconv::DigAll); + *self, rdx, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false); if special { fail!("number has a special value, \ try to_str_radix_special() if those are expected") } r diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 95e5797ae93..33ee4acf58b 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -720,7 +720,7 @@ impl Float for f64 { #[inline] pub fn to_str(num: f64) -> ~str { let (r, _) = strconv::float_to_str_common( - num, 10u, true, strconv::SignNeg, strconv::DigAll); + num, 10u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false); r } @@ -734,7 +734,7 @@ pub fn to_str(num: f64) -> ~str { #[inline] pub fn to_str_hex(num: f64) -> ~str { let (r, _) = strconv::float_to_str_common( - num, 16u, true, strconv::SignNeg, strconv::DigAll); + num, 16u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false); r } @@ -750,7 +750,7 @@ pub fn to_str_hex(num: f64) -> ~str { #[inline] pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) { strconv::float_to_str_common(num, rdx, true, - strconv::SignNeg, strconv::DigAll) + strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false) } /// @@ -765,7 +765,7 @@ pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) { #[inline] pub fn to_str_exact(num: f64, dig: uint) -> ~str { let (r, _) = strconv::float_to_str_common( - num, 10u, true, strconv::SignNeg, strconv::DigExact(dig)); + num, 10u, true, strconv::SignNeg, strconv::DigExact(dig), strconv::ExpNone, false); r } @@ -781,7 +781,7 @@ pub fn to_str_exact(num: f64, dig: uint) -> ~str { #[inline] pub fn to_str_digits(num: f64, dig: uint) -> ~str { let (r, _) = strconv::float_to_str_common( - num, 10u, true, strconv::SignNeg, strconv::DigMax(dig)); + num, 10u, true, strconv::SignNeg, strconv::DigMax(dig), strconv::ExpNone, false); r } @@ -806,7 +806,7 @@ impl num::ToStrRadix for f64 { #[inline] fn to_str_radix(&self, rdx: uint) -> ~str { let (r, special) = strconv::float_to_str_common( - *self, rdx, true, strconv::SignNeg, strconv::DigAll); + *self, rdx, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false); if special { fail!("number has a special value, \ try to_str_radix_special() if those are expected") } r diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index bf9e6b739f2..30abe86866e 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -207,11 +207,13 @@ pub fn int_to_str_bytes_common<T:NumCast * # Arguments * - `num` - The number to convert. Accepts any number that * implements the numeric traits. - * - `radix` - Base to use. Accepts only the values 2-36. + * - `radix` - Base to use. Accepts only the values 2-36. If the exponential notation + * is used, then this base is only used for the significand. The exponent + * itself always printed using a base of 10. * - `negative_zero` - Whether to treat the special value `-0` as * `-0` or as `+0`. * - `sign` - How to emit the sign. Options are: - * - `SignNone`: No sign at all. Basically emits `abs(num)`. + * - `SignNone`: No sign at all. The exponent sign is also omitted. * - `SignNeg`: Only `-` on negative values. * - `SignAll`: Both `+` on positive, and `-` on negative numbers. * - `digits` - The amount of digits to use for emitting the @@ -220,6 +222,17 @@ pub fn int_to_str_bytes_common<T:NumCast * fractions! * - `DigMax(uint)`: Maximum N digits, truncating any trailing zeros. * - `DigExact(uint)`: Exactly N digits. + * - `exp_format` - Whether or not to use the exponential (scientific) notation. + * Options are: + * - `ExpNone`: Do not use the exponential notation. + * - `ExpDec`: Use the exponential notation with the exponent having a base of 10, + * and exponent sign being `'e'` or `'E'` depending on the value of + * the `exp_upper` argument. E.g. the number 1000 would be printed as 1e3. + * - `ExpBin`: Use the exponential notation with the exponent having a base of 2, + * and exponent sign being `'p'` or `'P'` depending on the value of + * the `exp_upper` argument. E.g. the number 8 would be printed as 1p3. + * - `exp_capital` - Whether or not to use a capital letter for the exponent sign, if + * exponential notation is desired. * * # Return value * A tuple containing the byte vector, and a boolean flag indicating @@ -229,12 +242,26 @@ pub fn int_to_str_bytes_common<T:NumCast * * # Failure * - Fails if `radix` < 2 or `radix` > 36. + * - Fails if `radix` > 14 and `exp_format` is `ExpDec` due to conflict + * between digit and exponent sign `'e'`. + * - Fails if `radix` > 25 and `exp_format` is `ExpBin` due to conflict + * between digit and exponent sign `'p'`. */ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+Round+ Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>( num: T, radix: uint, negative_zero: bool, - sign: SignFormat, digits: SignificantDigits) -> (~[u8], bool) { + sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_upper: bool + ) -> (~[u8], bool) { assert!(2 <= radix && radix <= 36); + match exp_format { + ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e' + => fail!("float_to_str_bytes_common: radix {} incompatible with \ + use of 'e' as decimal exponent", radix), + ExpBin if radix >= DIGIT_P_RADIX // binary exponent 'p' + => fail!("float_to_str_bytes_common: radix {} incompatible with \ + use of 'p' as binary exponent", radix), + _ => () + } let _0: T = Zero::zero(); let _1: T = One::one(); @@ -260,6 +287,23 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+Round+ let mut buf: ~[u8] = ~[]; let radix_gen: T = cast(radix as int).unwrap(); + let (num, exp) = match exp_format { + ExpNone => (num, 0i32), + ExpDec | ExpBin => { + if num == _0 { + (num, 0i32) + } else { + let (exp, exp_base) = match exp_format { + ExpDec => (num.abs().log10().floor(), cast::<f64, T>(10.0f64).unwrap()), + ExpBin => (num.abs().log2().floor(), cast::<f64, T>(2.0f64).unwrap()), + ExpNone => unreachable!() + }; + + (num / exp_base.powf(&exp), cast::<T, i32>(exp).unwrap()) + } + } + }; + // First emit the non-fractional part, looping at least once to make // sure at least a `0` gets emitted. let mut deccum = num.trunc(); @@ -413,6 +457,21 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+Round+ } } + match exp_format { + ExpNone => (), + _ => { + buf.push(match exp_format { + ExpDec if exp_upper => 'E', + ExpDec if !exp_upper => 'e', + ExpBin if exp_upper => 'P', + ExpBin if !exp_upper => 'p', + _ => unreachable!() + } as u8); + + int_to_str_bytes_common(exp, 10, sign, |c| buf.push(c)); + } + } + (buf, false) } @@ -424,9 +483,10 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+Round+ pub fn float_to_str_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Float+Round+ Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>( num: T, radix: uint, negative_zero: bool, - sign: SignFormat, digits: SignificantDigits) -> (~str, bool) { + sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_capital: bool + ) -> (~str, bool) { let (bytes, special) = float_to_str_bytes_common(num, radix, - negative_zero, sign, digits); + negative_zero, sign, digits, exp_format, exp_capital); (str::from_utf8_owned(bytes).unwrap(), special) } |
