mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 15:01:51 +00:00
Add float support to #fmt. Fix #1014.
This commit is contained in:
parent
599baf9325
commit
43cb74b830
@ -196,6 +196,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, pieces: [piece], args: [@ast::expr])
|
||||
ty_int(s) {
|
||||
alt s { signed. { ret true; } unsigned. { ret false; } }
|
||||
}
|
||||
ty_float. { ret true; }
|
||||
_ { ret false; }
|
||||
}
|
||||
}
|
||||
@ -250,6 +251,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, pieces: [piece], args: [@ast::expr])
|
||||
ty_hex(_) { ret make_conv_call(cx, arg.span, "uint", cnv, arg); }
|
||||
ty_bits. { ret make_conv_call(cx, arg.span, "uint", cnv, arg); }
|
||||
ty_octal. { ret make_conv_call(cx, arg.span, "uint", cnv, arg); }
|
||||
ty_float. { ret make_conv_call(cx, arg.span, "float", cnv, arg); }
|
||||
_ { cx.span_unimpl(sp, unsupported); }
|
||||
}
|
||||
}
|
||||
@ -301,6 +303,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, pieces: [piece], args: [@ast::expr])
|
||||
}
|
||||
}
|
||||
ty_octal. { log "type: octal"; }
|
||||
ty_float. { log "type: float"; }
|
||||
}
|
||||
}
|
||||
let fmt_sp = args[0].span;
|
||||
|
@ -49,6 +49,7 @@ mod ct {
|
||||
ty_bits;
|
||||
ty_hex(caseness);
|
||||
ty_octal;
|
||||
ty_float;
|
||||
// FIXME: More types
|
||||
}
|
||||
tag flag {
|
||||
@ -246,6 +247,8 @@ mod ct {
|
||||
ty_bits
|
||||
} else if str::eq(tstr, "o") {
|
||||
ty_octal
|
||||
} else if str::eq(tstr, "f") {
|
||||
ty_float
|
||||
} else { error("unknown type in conversion: " + tstr) };
|
||||
ret {ty: t, next: i + 1u};
|
||||
}
|
||||
@ -328,6 +331,21 @@ mod rt {
|
||||
};
|
||||
ret pad(cv, unpadded, pad_nozero);
|
||||
}
|
||||
fn conv_float(cv: conv, f: float) -> str {
|
||||
let (to_str, digits) = alt cv.precision {
|
||||
count_is(c) { (float::to_str_exact, c as uint) }
|
||||
count_implied. { (float::to_str, 6u) }
|
||||
};
|
||||
let s = to_str(f, digits);
|
||||
if 0.0 <= f {
|
||||
if have_flag(cv.flags, flag_sign_always) {
|
||||
s = "+" + s;
|
||||
} else if have_flag(cv.flags, flag_space_for_sign) {
|
||||
s = " " + s;
|
||||
}
|
||||
}
|
||||
ret pad(cv, s, pad_signed);
|
||||
}
|
||||
|
||||
// Convert an int to string with minimum number of digits. If precision is
|
||||
// 0 and num is 0 then the result is the empty string.
|
||||
|
@ -7,16 +7,17 @@ Module: float
|
||||
*/
|
||||
|
||||
/*
|
||||
Function: to_str
|
||||
Function: to_str_common
|
||||
|
||||
Converts a float to a string
|
||||
|
||||
Parameters:
|
||||
|
||||
num - The float value
|
||||
digits: The number of significant digits
|
||||
digits - The number of significant digits
|
||||
exact - Whether to enforce the exact number of significant digits
|
||||
*/
|
||||
fn to_str(num: float, digits: uint) -> str {
|
||||
fn to_str_common(num: float, digits: uint, exact: bool) -> str {
|
||||
let (num, accum) = num < 0.0 ? (-num, "-") : (num, "");
|
||||
let trunc = num as uint;
|
||||
let frac = num - (trunc as float);
|
||||
@ -24,14 +25,46 @@ fn to_str(num: float, digits: uint) -> str {
|
||||
if frac == 0.0 || digits == 0u { ret accum; }
|
||||
accum += ".";
|
||||
let i = digits;
|
||||
while i > 0u && frac > 0.0 {
|
||||
let epsilon = 1. / pow_uint_to_uint_as_float(10u, i);
|
||||
while i > 0u && (frac >= epsilon || exact) {
|
||||
frac *= 10.0;
|
||||
epsilon *= 10.0;
|
||||
let digit = frac as uint;
|
||||
accum += uint::str(digit);
|
||||
frac -= digit as float;
|
||||
i -= 1u;
|
||||
}
|
||||
ret accum;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Function: to_str
|
||||
|
||||
Converts a float to a string with exactly the number of provided significant
|
||||
digits
|
||||
|
||||
Parameters:
|
||||
|
||||
num - The float value
|
||||
digits - The number of significant digits
|
||||
*/
|
||||
fn to_str_exact(num: float, digits: uint) -> str {
|
||||
to_str_common(num, digits, true)
|
||||
}
|
||||
|
||||
/*
|
||||
Function: to_str
|
||||
|
||||
Converts a float to a string with a maximum number of significant digits
|
||||
|
||||
Parameters:
|
||||
|
||||
num - The float value
|
||||
digits - The number of significant digits
|
||||
*/
|
||||
fn to_str(num: float, digits: uint) -> str {
|
||||
to_str_common(num, digits, false)
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -38,6 +38,7 @@ fn part1() {
|
||||
test(#fmt["%X", 0x12ab_u], "12AB");
|
||||
test(#fmt["%o", 10u], "12");
|
||||
test(#fmt["%t", 0b11010101_u], "11010101");
|
||||
test(#fmt["%f", 5.82], "5.82");
|
||||
// 32-bit limits
|
||||
|
||||
test(#fmt["%i", -2147483648], "-2147483648");
|
||||
@ -61,6 +62,7 @@ fn part2() {
|
||||
test(#fmt["%10o", 10u], " 12");
|
||||
test(#fmt["%10t", 0xff_u], " 11111111");
|
||||
test(#fmt["%10c", 'A'], " A");
|
||||
test(#fmt["%10f", 5.82], " 5.82");
|
||||
// Left justify
|
||||
|
||||
test(#fmt["%-10d", 500], "500 ");
|
||||
@ -73,6 +75,7 @@ fn part2() {
|
||||
test(#fmt["%-10o", 10u], "12 ");
|
||||
test(#fmt["%-10t", 0xff_u], "11111111 ");
|
||||
test(#fmt["%-10c", 'A'], "A ");
|
||||
test(#fmt["%-10f", 5.82], "5.82 ");
|
||||
}
|
||||
|
||||
fn part3() {
|
||||
@ -90,6 +93,7 @@ fn part3() {
|
||||
test(#fmt["%.o", 10u], "12");
|
||||
test(#fmt["%.t", 3u], "11");
|
||||
test(#fmt["%.c", 'A'], "A");
|
||||
test(#fmt["%.f", 5.82], "5");
|
||||
test(#fmt["%.0d", 0], "");
|
||||
test(#fmt["%.0u", 0u], "");
|
||||
test(#fmt["%.0x", 0u], "");
|
||||
@ -102,6 +106,7 @@ fn part3() {
|
||||
test(#fmt["%.0o", 10u], "12");
|
||||
test(#fmt["%.0t", 3u], "11");
|
||||
test(#fmt["%.0c", 'A'], "A");
|
||||
test(#fmt["%.0f", 5.892], "5");
|
||||
test(#fmt["%.1d", 0], "0");
|
||||
test(#fmt["%.1u", 0u], "0");
|
||||
test(#fmt["%.1x", 0u], "0");
|
||||
@ -114,6 +119,7 @@ fn part3() {
|
||||
test(#fmt["%.1o", 10u], "12");
|
||||
test(#fmt["%.1t", 3u], "11");
|
||||
test(#fmt["%.1c", 'A'], "A");
|
||||
test(#fmt["%.1f", 5.82], "5.8");
|
||||
}
|
||||
fn part4() {
|
||||
test(#fmt["%.5d", 0], "00000");
|
||||
@ -128,6 +134,7 @@ fn part4() {
|
||||
test(#fmt["%.5o", 10u], "00012");
|
||||
test(#fmt["%.5t", 3u], "00011");
|
||||
test(#fmt["%.5c", 'A'], "A");
|
||||
test(#fmt["%.5f", 5.82], "5.82000");
|
||||
// Bool precision. I'm not sure if it's good or bad to have bool
|
||||
// conversions support precision - it's not standard printf so we
|
||||
// can do whatever. For now I'm making it behave the same as string
|
||||
@ -144,15 +151,19 @@ fn part5() {
|
||||
test(#fmt["%+d", 0], "+0");
|
||||
test(#fmt["%+d", 1], "+1");
|
||||
test(#fmt["%+d", -1], "-1");
|
||||
test(#fmt["%+f", 0.0], "+0");
|
||||
// Leave space for sign
|
||||
|
||||
test(#fmt["% d", 0], " 0");
|
||||
test(#fmt["% d", 1], " 1");
|
||||
test(#fmt["% d", -1], "-1");
|
||||
test(#fmt["% f", 0.0], " 0");
|
||||
// Plus overrides space
|
||||
|
||||
test(#fmt["% +d", 0], "+0");
|
||||
test(#fmt["%+ d", 0], "+0");
|
||||
test(#fmt["% +f", 0.0], "+0");
|
||||
test(#fmt["%+ f", 0.0], "+0");
|
||||
// 0-padding
|
||||
|
||||
test(#fmt["%05d", 0], "00000");
|
||||
@ -163,6 +174,7 @@ fn part5() {
|
||||
test(#fmt["%05X", 127u], "0007F");
|
||||
test(#fmt["%05o", 10u], "00012");
|
||||
test(#fmt["%05t", 3u], "00011");
|
||||
test(#fmt["%05f", 5.82], "05.82");
|
||||
// 0-padding a string is undefined but glibc does this:
|
||||
|
||||
test(#fmt["%05s", "test"], " test");
|
||||
@ -181,6 +193,7 @@ fn part5() {
|
||||
test(#fmt["%-05s", "test"], "test ");
|
||||
test(#fmt["%-05c", 'A'], "A ");
|
||||
test(#fmt["%-05b", true], "true ");
|
||||
test(#fmt["%-05f", 5.82], "5.82 ");
|
||||
}
|
||||
fn part6() {
|
||||
// Precision overrides 0-padding
|
||||
@ -196,6 +209,7 @@ fn part6() {
|
||||
test(#fmt["%06.5x", 127u], " 0007f");
|
||||
test(#fmt["%06.5X", 127u], " 0007F");
|
||||
test(#fmt["%06.5o", 10u], " 00012");
|
||||
test(#fmt["%08.5f", 5.82], " 5.82000");
|
||||
// Signed combinations
|
||||
|
||||
test(#fmt["% 5d", 1], " 1");
|
||||
|
Loading…
Reference in New Issue
Block a user