float_to_str_bytes_common can now handle exponential notation
This commit is contained in:
parent
fce792249e
commit
2b4bd0780b
@ -718,7 +718,7 @@ fn integer_decode(&self) -> (u64, i16, i8) {
|
||||
#[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
|
||||
|
@ -720,7 +720,7 @@ fn integer_decode(&self) -> (u64, i16, i8) {
|
||||
#[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
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user