Skip to content

Commit

Permalink
strconv: fix e/g format (fix #22424) (#22430)
Browse files Browse the repository at this point in the history
  • Loading branch information
kbkpbot authored Oct 7, 2024
1 parent 502442a commit 309c8d3
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 11 deletions.
8 changes: 6 additions & 2 deletions vlib/builtin/string_interpolation.v
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,9 @@ fn (data &StrIntpData) process_str_intp_data(mut sb strings.Builder) {
f.free()
return
}
// NOTE: For 'g' and 'G' bf.len1 is the maximum number of significant digits.
// Not like 'e' or 'E', which is the number of digits after the decimal point.
bf.len1--
mut f := strconv.format_es(data.d.d_f32, bf)
if upper_case {
tmp := f
Expand Down Expand Up @@ -582,6 +585,9 @@ fn (data &StrIntpData) process_str_intp_data(mut sb strings.Builder) {
f.free()
return
}
// NOTE: For 'g' and 'G' bf.len1 is the maximum number of significant digits
// Not like 'e' or 'E', which is the number of digits after the decimal point.
bf.len1--
mut f := strconv.format_es(data.d.d_f64, bf)
if upper_case {
tmp := f
Expand All @@ -595,7 +601,6 @@ fn (data &StrIntpData) process_str_intp_data(mut sb strings.Builder) {
.si_e32 {
$if !nofloat ? {
// println("HERE: e32")
bf.len1 = 6
if use_default_str {
mut f := data.d.d_f32.str()
if upper_case {
Expand Down Expand Up @@ -623,7 +628,6 @@ fn (data &StrIntpData) process_str_intp_data(mut sb strings.Builder) {
.si_e64 {
$if !nofloat ? {
// println("HERE: e64")
bf.len1 = 6
if use_default_str {
mut f := data.d.d_f64.str()
if upper_case {
Expand Down
22 changes: 13 additions & 9 deletions vlib/strconv/f64_str.c.v
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ https://github.com/cespare/ryu/tree/ba56a33f39e3bbbfa409095d0f9ae168a595feea

@[direct_array_access]
fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string {
mut n_digit := i_n_digit + 1
mut n_digit := if i_n_digit < 1 { 1 } else { i_n_digit + 1 }
pad_digit := i_pad_digit + 1
mut out := d.m
mut d_exp := d.e
Expand Down Expand Up @@ -54,7 +54,10 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string {
out += ten_pow_table_64[out_len - n_digit - 1] * 5 // round to up
out /= ten_pow_table_64[out_len - n_digit]
// println("out1:[$out] ${d.m / ten_pow_table_64[out_len - n_digit ]}")
if d.m / ten_pow_table_64[out_len - n_digit] < out {
// fix issue #22424
out_div := d.m / ten_pow_table_64[out_len - n_digit]
if out_div < out && dec_digits(out_div) < dec_digits(out) {
// from `99` to `100`, will need d_exp+1
d_exp++
n_digit++
}
Expand All @@ -74,13 +77,14 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string {
x++
}

// fix issue #22424
// no decimal digits needed, end here
if i_n_digit == 0 {
unsafe {
buf[i] = 0
return tos(&u8(&buf[0]), i)
}
}
// if i_n_digit == 0 {
// unsafe {
// buf[i] = 0
// return tos(&u8(&buf[0]), i)
// }
//}

if out_len >= 1 {
buf[y - x] = `.`
Expand Down Expand Up @@ -365,7 +369,7 @@ pub fn f64_to_str_pad(f f64, n_digit int) string {
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}")
// unsafe { println("s:${neg} mant:${mant} exp:${exp} float:${f} byte:${u1.u:016x}") }

// Exit early for easy cases.
if exp == maxexp64 || (exp == 0 && mant == 0) {
Expand Down
19 changes: 19 additions & 0 deletions vlib/strconv/format_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,22 @@ fn test_remove_tail_zeros() {
assert strconv.remove_tail_zeros('1234') == '1234'
assert strconv.remove_tail_zeros('1.00000000007') == '1.00000000007'
}

fn test_g_format() {
a := 1234.56789000e10
assert '${a:1.0g}' == '1e+13'
assert '${a:1.1g}' == '1e+13'
assert '${a:1.2g}' == '1.2e+13'
assert '${a:1.3g}' == '1.23e+13'
assert '${a:1.4g}' == '1.235e+13'
assert '${a:1.5g}' == '1.2346e+13'
assert '${a:1.6g}' == '1.23457e+13'
assert '${a:1.7g}' == '1.234568e+13'
assert '${a:1.8g}' == '1.2345679e+13'
assert '${a:1.9g}' == '1.23456789e+13'
assert '${a:1.10g}' == '1.23456789e+13'
assert '${a:1.11g}' == '1.23456789e+13'
assert '${a:1.12g}' == '1.23456789e+13'

// TODO: e format not support due to issue #22429
}

0 comments on commit 309c8d3

Please sign in to comment.