strconv: fix on ftoa string decimal aproximation, 'nan' string fix

pull/4125/head
penguindark 2020-03-26 22:39:46 +01:00 committed by GitHub
parent 9185de3fb7
commit 8de027c4b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 27 deletions

View File

@ -165,4 +165,8 @@ fn test_float_to_str(){
//println(b)
assert b.len == exp + 2
}
// test rounding str conversion
assert f64_to_str(0.3456789123456, 4)=="3.4568e-01"
assert f32_to_str(0.345678, 3)=="3.457e-01"
}

View File

@ -33,6 +33,24 @@ mut:
u u32
}
// pow of ten table used by n_digit reduction
const(
ten_pow_table_32 = [
u32(1),
u32(10),
u32(100),
u32(1000),
u32(10000),
u32(100000),
u32(1000000),
u32(10000000),
u32(100000000),
u32(1000000000),
u32(10000000000),
u32(100000000000),
]
)
/******************************************************************************
*
* Conversion Functions
@ -47,17 +65,15 @@ const(
// max 46 char
// -3.40282346638528859811704183484516925440e+38
fn (d Dec32) get_string_32(neg bool, n_digit int) string {
mut out := d.m
mut out_len := decimal_len_32(out)
fn (d Dec32) get_string_32(neg bool, i_n_digit int) string {
n_digit := i_n_digit + 1
mut out := d.m
mut out_len := decimal_len_32(out)
out_len_original := out_len
mut buf := [byte(0)].repeat(out_len + 5 + 1 +1) // sign + mant_len + . + e + e_sign + exp_len(2) + \0
mut i := 0
if n_digit > 0 && out_len > n_digit {
out_len = n_digit+1
}
if neg {
buf[i]=`-`
i++
@ -68,6 +84,13 @@ fn (d Dec32) get_string_32(neg bool, n_digit int) string {
disp = 1
}
if n_digit < out_len {
//println("orig: ${out_len_original}")
out += ten_pow_table_32[out_len - n_digit] + 1 // round to up
out /= ten_pow_table_32[out_len - n_digit]
out_len = n_digit
}
y := i + out_len
mut x := 0
for x < (out_len-disp-1) {
@ -100,7 +123,7 @@ fn (d Dec32) get_string_32(neg bool, n_digit int) string {
buf[i]=`e`
i++
mut exp := d.e + out_len - 1
mut exp := d.e + out_len_original - 1
if exp < 0 {
buf[i]=`-`
i++

View File

@ -39,6 +39,32 @@ mut:
u u64
}
// pow of ten table used by n_digit reduction
const(
ten_pow_table_64 = [
u64(1),
u64(10),
u64(100),
u64(1000),
u64(10000),
u64(100000),
u64(1000000),
u64(10000000),
u64(100000000),
u64(1000000000),
u64(10000000000),
u64(100000000000),
u64(1000000000000),
u64(10000000000000),
u64(100000000000000),
u64(1000000000000000),
u64(10000000000000000),
u64(100000000000000000),
u64(1000000000000000000),
u64(10000000000000000000),
]
)
/******************************************************************************
*
* Conversion Functions
@ -51,17 +77,15 @@ const(
maxexp64 = 2047
)
fn (d Dec64) get_string_64(neg bool, n_digit int) string {
mut out := d.m
mut out_len := decimal_len_64(out)
fn (d Dec64) get_string_64(neg bool, i_n_digit int) string {
n_digit := i_n_digit + 1
mut out := d.m
mut out_len := decimal_len_64(out)
out_len_original := out_len
mut buf := [byte(0)].repeat(out_len + 6 + 1 +1) // sign + mant_len + . + e + e_sign + exp_len(2) + \0
mut i := 0
if n_digit > 0 && out_len > n_digit {
out_len = n_digit+1
}
if neg {
buf[i]=`-`
i++
@ -72,6 +96,13 @@ fn (d Dec64) get_string_64(neg bool, n_digit int) string {
disp = 1
}
if n_digit < out_len {
//println("orig: ${out_len_original}")
out += ten_pow_table_64[out_len - n_digit] + 1 // round to up
out /= ten_pow_table_64[out_len - n_digit]
out_len = n_digit
}
y := i + out_len
mut x := 0
for x < (out_len-disp-1) {
@ -104,7 +135,7 @@ fn (d Dec64) get_string_64(neg bool, n_digit int) string {
buf[i]=`e`
i++
mut exp := d.e + out_len - 1
mut exp := d.e + out_len_original - 1
if exp < 0 {
buf[i]=`-`
i++
@ -114,16 +145,6 @@ fn (d Dec64) get_string_64(neg bool, n_digit int) string {
i++
}
// Always print two digits to match strconv's formatting.
/* d1 := exp % 10
d0 := exp / 10
buf[i]=`0` + byte(d0)
i++
buf[i]=`0` + byte(d1)
i++
buf[i]=0
*/
// Always print at least two digits to match strconv's formatting.
d2 := exp % 10
exp /= 10

View File

@ -233,7 +233,7 @@ pub fn f64_to_str_l(f f64) string {
s := f64_to_str(f,18)
// check for +inf -inf Nan
if s.len > 2 && (s[0] == `N` || s[1] == `i`) {
if s.len > 2 && (s[0] == `n` || s[1] == `i`) {
return s
}