Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

strconv: fix e/g format #22430

Merged
merged 2 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
// }
//}
Comment on lines -78 to +87
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imho just delete sections of dead code, instead of commenting them.


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
}
spytheman marked this conversation as resolved.
Show resolved Hide resolved
Loading