Skip to content

Commit a8e0c9e

Browse files
authored
strconv: produce a maximum of 8 digits after the . for f32.str() (fix #25141) (#25144)
1 parent aa7de61 commit a8e0c9e

File tree

5 files changed

+76
-13
lines changed

5 files changed

+76
-13
lines changed

vlib/strconv/f32_f64_to_string_test.v

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,35 @@ fn test_float_to_str() {
172172
// assert ftoa.f64_to_str(0.3456789123456, 4)=="3.4568e-01"
173173
// assert ftoa.f32_to_str(0.345678, 3)=="3.457e-01"
174174
}
175+
176+
fn test_issue_25141_1() {
177+
assert strconv.ftoa_long_32(0.1234567901) == '0.12345679'
178+
}
179+
180+
fn test_issue_25141_2() {
181+
assert strconv.f32_to_str_l(math.f32_from_bits(1055100472)) == '0.44444442'
182+
}
183+
184+
fn test_issue_25141_3() {
185+
assert strconv.f32_to_str_l(math.f32_from_bits(1055100473)) == '0.44444445'
186+
}
187+
188+
fn test_issue_25141_4() {
189+
assert strconv.f32_to_str_l(math.f32_from_bits(1055100474)) == '0.44444448'
190+
}
191+
192+
fn test_issue_25141_5() {
193+
assert strconv.f32_to_str_l(math.f32_from_bits(1055100475)) == '0.4444445'
194+
}
195+
196+
fn test_issue_25141_0001() {
197+
assert strconv.f32_to_str_l(math.f32_from_bits(953267991)) == '0.0001'
198+
assert strconv.f32_to_str_l(math.f32_from_bits(953267992)) == '0.000100000005'
199+
assert strconv.f32_to_str_l(math.f32_from_bits(953267993)) == '0.00010000001'
200+
assert strconv.f32_to_str_l(math.f32_from_bits(953267994)) == '0.00010000002'
201+
assert strconv.f32_to_str_l(math.f32_from_bits(953267995)) == '0.00010000003'
202+
assert strconv.f32_to_str_l(math.f32_from_bits(953267996)) == '0.000100000034'
203+
assert strconv.f32_to_str_l(math.f32_from_bits(953267997)) == '0.00010000004'
204+
assert strconv.f32_to_str_l(math.f32_from_bits(953267998)) == '0.00010000005'
205+
assert strconv.f32_to_str_l(math.f32_from_bits(953267999)) == '0.000100000056'
206+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import math
2+
3+
fn test_around() {
4+
// do not pass 0
5+
for f in [f32(1e-12), 1e-9, 1e-6, 1e-4, 0.1, 0.2, 0.5, 1, 2, 5, 10, 1e6, 1e7, 1e9, 1e12] {
6+
check_around(f, 1000)
7+
}
8+
}
9+
10+
fn check_around(fval f32, total int) {
11+
check(fval, total)
12+
check(-fval, total)
13+
}
14+
15+
fn check(fval f32, total int) {
16+
middle_bits := math.f32_bits(fval)
17+
start_bits := middle_bits - u32(total / 2)
18+
end_bits := middle_bits + u32(total / 2)
19+
min, max := if start_bits < end_bits { start_bits, end_bits } else { end_bits, start_bits }
20+
println('> check_around ${total} f32 values around fval: ${fval:26.12f}, middle_bits for fval: ${middle_bits:12} | min: ${min:12} | max: ${max:12}')
21+
for ux in min .. max {
22+
x := math.f32_from_bits(ux)
23+
if math.is_nan(x) {
24+
continue
25+
}
26+
uy := ux - 1
27+
y := math.f32_from_bits(uy)
28+
if x == y {
29+
continue
30+
}
31+
sx := x.str()
32+
sy := y.str()
33+
assert sx != sy, 'math.f32_from_bits(${ux})'
34+
}
35+
}

vlib/strconv/ftoa.c.v

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,32 +19,28 @@ https://github.com/cespare/ryu/tree/ba56a33f39e3bbbfa409095d0f9ae168a595feea
1919
*/
2020

2121
// ftoa_64 returns a string in scientific notation with max 17 digits after the dot.
22-
//
2322
// Example: assert strconv.ftoa_64(123.1234567891011121) == '1.2312345678910111e+02'
2423
@[inline]
2524
pub fn ftoa_64(f f64) string {
2625
return f64_to_str(f, 17)
2726
}
2827

2928
// ftoa_long_64 returns `f` as a `string` in decimal notation with a maximum of 17 digits after the dot.
30-
//
3129
// Example: assert strconv.f64_to_str_l(123.1234567891011121) == '123.12345678910111'
3230
@[inline]
3331
pub fn ftoa_long_64(f f64) string {
3432
return f64_to_str_l(f)
3533
}
3634

3735
// ftoa_32 returns a `string` in scientific notation with max 8 digits after the dot.
38-
//
3936
// Example: assert strconv.ftoa_32(34.1234567) == '3.4123455e+01'
4037
@[inline]
4138
pub fn ftoa_32(f f32) string {
4239
return f32_to_str(f, 8)
4340
}
4441

45-
// ftoa_long_32 returns `f` as a `string` in decimal notation with a maximum of 6 digits after the dot.
46-
//
47-
// Example: assert strconv.ftoa_long_32(34.1234567) == '34.12346'
42+
// ftoa_long_32 returns `f` as a `string` in decimal notation with a maximum of 8 digits after the dot.
43+
// Example: assert strconv.ftoa_long_32(0.1234567901) == '0.12345679'
4844
@[inline]
4945
pub fn ftoa_long_32(f f32) string {
5046
return f32_to_str_l(f)

vlib/strconv/utilities.c.v

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,24 @@ f64 to string with string format
2323
*/
2424

2525
// TODO: Investigate precision issues
26-
// f32_to_str_l returns `f` as a `string` in decimal notation with a maximum of 6 digits after the dot.
27-
//
28-
// Example: assert strconv.f32_to_str_l(34.1234567) == '34.12346'
26+
// f32_to_str_l returns `f` as a `string` in decimal notation with a maximum of 8 digits after the dot.
27+
// Example: assert strconv.f32_to_str_l(0.1234567891) == '0.12345679'
28+
// Example: assert strconv.f32_to_str_l(34.1234567891) == '34.123455'
2929
@[manualfree]
3030
pub fn f32_to_str_l(f f32) string {
31-
s := f32_to_str(f, 6)
31+
s := f32_to_str(f, 8)
3232
res := fxx_to_str_l_parse(s)
3333
unsafe { s.free() }
3434
return res
3535
}
3636

37-
// f32_to_str_l_with_dot returns `f` as a `string` in decimal notation with a maximum of 6 digits after the dot.
37+
// f32_to_str_l_with_dot returns `f` as a `string` in decimal notation with a maximum of 8 digits after the dot.
3838
// If the decimal digits after the dot are zero, a '.0' is appended for clarity.
3939
//
4040
// Example: assert strconv.f32_to_str_l_with_dot(34.) == '34.0'
4141
@[manualfree]
4242
pub fn f32_to_str_l_with_dot(f f32) string {
43-
s := f32_to_str(f, 6)
43+
s := f32_to_str(f, 8)
4444
res := fxx_to_str_l_parse_with_dot(s)
4545
unsafe { s.free() }
4646
return res

vlib/v/slow_tests/repl/fn_calls.repl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ fn test() { println('foo') } fn test2(a int) { println(a) }
44
test()
55
test2(123)
66
===output===
7-
-0.2623749
7+
-0.26237485
88
0.7376251
99
foo
1010
123

0 commit comments

Comments
 (0)