mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
correctly rounded floating-point conversions
in new package strconv. move atoi etc to strconv too. update fmt, etc to use strconv. R=r DELTA=2232 (1691 added, 424 deleted, 117 changed) OCL=19286 CL=19380
This commit is contained in:
parent
f333f4685c
commit
079c00a475
24 changed files with 1819 additions and 530 deletions
|
|
@ -115,272 +115,3 @@ export func join(a *[]string, sep string) string {
|
|||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// Convert decimal string to unsigned integer.
|
||||
// TODO: Doesn't check for overflow.
|
||||
export func atoui64(s string) (i uint64, ok bool) {
|
||||
// empty string bad
|
||||
if len(s) == 0 {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// pick off zero
|
||||
if s == "0" {
|
||||
return 0, true
|
||||
}
|
||||
|
||||
// otherwise, leading zero bad
|
||||
if s[0] == '0' {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// parse number
|
||||
n := uint64(0);
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] < '0' || s[i] > '9' {
|
||||
return 0, false
|
||||
}
|
||||
n = n*10 + uint64(s[i] - '0')
|
||||
}
|
||||
return n, true
|
||||
}
|
||||
|
||||
// Convert decimal string to integer.
|
||||
// TODO: Doesn't check for overflow.
|
||||
export func atoi64(s string) (i int64, ok bool) {
|
||||
// empty string bad
|
||||
if len(s) == 0 {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// pick off leading sign
|
||||
neg := false;
|
||||
if s[0] == '+' {
|
||||
s = s[1:len(s)]
|
||||
} else if s[0] == '-' {
|
||||
neg = true;
|
||||
s = s[1:len(s)]
|
||||
}
|
||||
|
||||
var un uint64;
|
||||
un, ok = atoui64(s);
|
||||
if !ok {
|
||||
return 0, false
|
||||
}
|
||||
n := int64(un);
|
||||
if neg {
|
||||
n = -n
|
||||
}
|
||||
return n, true
|
||||
}
|
||||
|
||||
export func atoui(s string) (i uint, ok bool) {
|
||||
ii, okok := atoui64(s);
|
||||
i = uint(ii);
|
||||
return i, okok
|
||||
}
|
||||
|
||||
export func atoi(s string) (i int, ok bool) {
|
||||
ii, okok := atoi64(s);
|
||||
i = int(ii);
|
||||
return i, okok
|
||||
}
|
||||
|
||||
export func ltoa(i int64) string {
|
||||
if i == 0 {
|
||||
return "0"
|
||||
}
|
||||
|
||||
neg := false; // negative
|
||||
u := uint(i);
|
||||
if i < 0 {
|
||||
neg = true;
|
||||
u = -u;
|
||||
}
|
||||
|
||||
// Assemble decimal in reverse order.
|
||||
var b [32]byte;
|
||||
bp := len(b);
|
||||
for ; u > 0; u /= 10 {
|
||||
bp--;
|
||||
b[bp] = byte(u%10) + '0'
|
||||
}
|
||||
if neg { // add sign
|
||||
bp--;
|
||||
b[bp] = '-'
|
||||
}
|
||||
|
||||
// BUG return string(b[bp:len(b)])
|
||||
return string((&b)[bp:len(b)])
|
||||
}
|
||||
|
||||
export func itoa(i int) string {
|
||||
return ltoa(int64(i));
|
||||
}
|
||||
|
||||
// Convert float64 to string. No control over format.
|
||||
// Result not great; only useful for simple debugging.
|
||||
export func f64toa(v float64) string {
|
||||
var buf [20]byte;
|
||||
|
||||
const n = 7; // digits printed
|
||||
e := 0; // exp
|
||||
var sign byte = '+';
|
||||
if(v != 0) {
|
||||
// sign
|
||||
if(v < 0) {
|
||||
v = -v;
|
||||
sign = '-';
|
||||
}
|
||||
|
||||
// normalize
|
||||
for v >= 10 {
|
||||
e++;
|
||||
v /= 10;
|
||||
}
|
||||
for v < 1 {
|
||||
e--;
|
||||
v *= 10;
|
||||
}
|
||||
|
||||
// round
|
||||
var h float64 = 5;
|
||||
for i := 0; i < n; i++ {
|
||||
h /= 10;
|
||||
}
|
||||
v += h;
|
||||
if v >= 10 {
|
||||
e++;
|
||||
v /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
// format +d.dddd+edd
|
||||
buf[0] = sign;
|
||||
for i := 0; i < n; i++ {
|
||||
s := int64(v);
|
||||
buf[i+2] = byte(s)+'0';
|
||||
v -= float64(s);
|
||||
v *= 10;
|
||||
}
|
||||
buf[1] = buf[2];
|
||||
buf[2] = '.';
|
||||
|
||||
buf[n+2] = 'e';
|
||||
buf[n+3] = '+';
|
||||
if e < 0 {
|
||||
e = -e;
|
||||
buf[n+3] = '-';
|
||||
}
|
||||
|
||||
// TODO: exponents > 99?
|
||||
buf[n+4] = byte((e/10) + '0');
|
||||
buf[n+5] = byte((e%10) + '0');
|
||||
return string(buf)[0:n+6]; // TODO: should be able to slice buf
|
||||
}
|
||||
|
||||
export func ftoa(v float) string {
|
||||
return f64toa(float64(v));
|
||||
}
|
||||
|
||||
export func f32toa(v float32) string {
|
||||
return f64toa(float64(v));
|
||||
}
|
||||
|
||||
// Simple conversion of string to floating point.
|
||||
// TODO: make much better. THIS CODE IS VERY WEAK.
|
||||
// Lets through some poor cases such as "." and "e4" and "1e-". Fine.
|
||||
export func atof64(s string) (f float64, ok bool) {
|
||||
// empty string bad
|
||||
if len(s) == 0 {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// pick off leading sign
|
||||
neg := false;
|
||||
if s[0] == '+' {
|
||||
s = s[1:len(s)]
|
||||
} else if s[0] == '-' {
|
||||
neg = true;
|
||||
s = s[1:len(s)]
|
||||
}
|
||||
|
||||
// parse number
|
||||
// first, left of the decimal point.
|
||||
n := uint64(0);
|
||||
i := 0;
|
||||
for ; i < len(s); i++ {
|
||||
if s[i] == '.' || s[i] == 'e' || s[i] == 'E' {
|
||||
break
|
||||
}
|
||||
if s[i] < '0' || s[i] > '9' {
|
||||
return 0, false
|
||||
}
|
||||
n = n*10 + uint64(s[i] - '0')
|
||||
}
|
||||
result := float64(n);
|
||||
if i != len(s) {
|
||||
frac := uint64(0);
|
||||
scale := float64(1);
|
||||
// decimal and fraction
|
||||
if s[i] == '.' {
|
||||
i++;
|
||||
for ; i < len(s); i++ {
|
||||
if s[i] == 'e' || s[i] == 'E' {
|
||||
break
|
||||
}
|
||||
if s[i] < '0' || s[i] > '9' {
|
||||
return 0, false
|
||||
}
|
||||
frac = frac*10 + uint64(s[i] - '0');
|
||||
scale = scale * 10.0;
|
||||
}
|
||||
}
|
||||
result += float64(frac)/scale;
|
||||
// exponent
|
||||
if i != len(s) { // must be 'e' or 'E'
|
||||
i++;
|
||||
eneg := false;
|
||||
if i < len(s) && s[i] == '-' {
|
||||
eneg = true;
|
||||
i++;
|
||||
} else if i < len(s) && s[i] == '+' {
|
||||
i++;
|
||||
}
|
||||
// this works ok for "1e+" - fine.
|
||||
exp := uint64(0);
|
||||
for ; i < len(s); i++ {
|
||||
if s[i] < '0' || s[i] > '9' {
|
||||
return 0, false
|
||||
}
|
||||
exp = exp*10 + uint64(s[i] - '0');
|
||||
}
|
||||
if eneg {
|
||||
for exp > 0 {
|
||||
result /= 10.0;
|
||||
exp--;
|
||||
}
|
||||
} else {
|
||||
for exp > 0 {
|
||||
result *= 10.0;
|
||||
exp--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if neg {
|
||||
result = -result
|
||||
}
|
||||
return result, true
|
||||
}
|
||||
|
||||
export func atof(s string) (f float, ok bool) {
|
||||
a, b := atof64(s);
|
||||
return float(a), b;
|
||||
}
|
||||
|
||||
export func atof32(s string) (f float32, ok bool) {
|
||||
a, b := atof64(s);
|
||||
return float32(a), b;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue