1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

ftoa: some fixes for rounding, new functions

This commit is contained in:
penguindark 2020-04-22 01:42:44 +02:00 committed by GitHub
parent b9c0d2d362
commit 34fd148f2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 84 additions and 9 deletions

View File

@ -65,12 +65,18 @@ const(
// max 46 char
// -3.40282346638528859811704183484516925440e+38
fn (d Dec32) get_string_32(neg bool, i_n_digit int) string {
fn (d Dec32) get_string_32(neg bool, i_n_digit int, i_pad_digit int) string {
n_digit := i_n_digit + 1
pad_digit := i_pad_digit + 1
mut out := d.m
mut out_len := decimal_len_32(out)
out_len_original := out_len
mut fw_zeros := 0
if pad_digit > out_len {
fw_zeros = pad_digit -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
@ -86,7 +92,7 @@ fn (d Dec32) get_string_32(neg bool, i_n_digit int) string {
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 - 1] * 5 // round to up
out /= ten_pow_table_32[out_len - n_digit]
out_len = n_digit
}
@ -111,6 +117,11 @@ fn (d Dec32) get_string_32(neg bool, i_n_digit int) string {
i++
}
for fw_zeros > 0 {
buf[i++] = `0`
fw_zeros--
}
/*
x=0
for x<buf.len {
@ -341,5 +352,32 @@ pub fn f32_to_str(f f32, n_digit int) string {
}
//println("${d.m} ${d.e}")
return d.get_string_32(neg, n_digit)
return d.get_string_32(neg, n_digit,0)
}
// f32_to_str return a string in scientific notation with max n_digit after the dot
pub fn f32_to_str_pad(f f32, n_digit int) string {
mut u1 := Uf32{}
u1.f = f
u := u1.u
neg := (u>>(mantbits32+expbits32)) != 0
mant := u & ((u32(1)<<mantbits32) - u32(1))
exp := (u >> mantbits32) & ((u32(1)<<expbits32) - u32(1))
//println("${neg} ${mant} e ${exp-bias32}")
// Exit early for easy cases.
if (exp == maxexp32) || (exp == 0 && mant == 0) {
return get_string_special(neg, exp == 0, mant == 0)
}
mut d, ok := f32_to_decimal_exact_int(mant, exp)
if !ok {
//println("with exp form")
d = f32_to_decimal(mant, exp)
}
//println("${d.m} ${d.e}")
return d.get_string_32(neg, n_digit, n_digit)
}

View File

@ -77,13 +77,19 @@ const(
maxexp64 = 2047
)
fn (d Dec64) get_string_64(neg bool, i_n_digit int) string {
fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string {
n_digit := i_n_digit + 1
pad_digit := i_pad_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 fw_zeros := 0
if pad_digit > out_len {
fw_zeros = pad_digit - out_len
}
mut buf := [byte(0)].repeat(out_len + 6 + 1 +1 + fw_zeros) // sign + mant_len + . + e + e_sign + exp_len(2) + \0
mut i := 0
if neg {
@ -96,11 +102,12 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int) string {
disp = 1
}
// rounding last used digit
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 - 1] * 5 // round to up
out /= ten_pow_table_64[out_len - n_digit ]
out_len = n_digit
//println("orig: ${out_len_original} new len: ${out_len}")
}
y := i + out_len
@ -123,6 +130,11 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int) string {
i++
}
for fw_zeros > 0 {
buf[i++] = `0`
fw_zeros--
}
/*
x=0
for x<buf.len {
@ -384,5 +396,30 @@ pub fn f64_to_str(f f64, n_digit int) string {
d = f64_to_decimal(mant, exp)
}
//println("${d.m} ${d.e}")
return d.get_string_64(neg, n_digit)
return d.get_string_64(neg, n_digit, 0)
}
// f64_to_str return a string in scientific notation with max n_digit after the dot
pub fn f64_to_str_pad(f f64, n_digit int) string {
mut u1 := Uf64{}
u1.f = f
u := u1.u
neg := (u>>(mantbits64+expbits64)) != 0
mant := u & ((u64(1)<<mantbits64) - u64(1))
exp := (u >> mantbits64) & ((u64(1)<<expbits64) - u64(1))
//println("s:${neg} mant:${mant} exp:${exp} float:${f} byte:${u1.u:016lx}")
// Exit early for easy cases.
if (exp == maxexp64) || (exp == 0 && mant == 0) {
return get_string_special(neg, exp == 0, mant == 0)
}
mut d, ok := f64_to_decimal_exact_int(mant, exp)
if !ok {
//println("to_decimal")
d = f64_to_decimal(mant, exp)
}
//println("DEBUG: ${d.m} ${d.e}")
return d.get_string_64(neg, n_digit, n_digit)
}