mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
builtin,strconv: append ".0", to float string representations, to ensure clarity (#16079)
This commit is contained in:
parent
29b1796791
commit
43b9a716c5
@ -1,6 +1,7 @@
|
||||
## V 0.3.2
|
||||
*Not yet released*
|
||||
- Remove the need for the `[console]` attribute in Windows GUI apps.
|
||||
- All floats outputs now have `.0` conditionally appended to them to improve clarity.
|
||||
|
||||
## V 0.3.1
|
||||
*31 Aug 2022*
|
||||
|
@ -19,10 +19,10 @@ pub fn (x f64) str() string {
|
||||
f: x
|
||||
}
|
||||
if f.u == strconv.double_minus_zero {
|
||||
return '-0'
|
||||
return '-0.0'
|
||||
}
|
||||
if f.u == strconv.double_plus_zero {
|
||||
return '0'
|
||||
return '0.0'
|
||||
}
|
||||
}
|
||||
abs_x := f64_abs(x)
|
||||
@ -37,11 +37,11 @@ pub fn (x f64) str() string {
|
||||
[inline]
|
||||
pub fn (x f64) strg() string {
|
||||
if x == 0 {
|
||||
return '0'
|
||||
return '0.0'
|
||||
}
|
||||
abs_x := f64_abs(x)
|
||||
if abs_x >= 0.0001 && abs_x < 1.0e6 {
|
||||
return strconv.f64_to_str_l_no_dot(x)
|
||||
return strconv.f64_to_str_l_with_dot(x)
|
||||
} else {
|
||||
return strconv.ftoa_64(x)
|
||||
}
|
||||
@ -85,10 +85,10 @@ pub fn (x f32) str() string {
|
||||
f: x
|
||||
}
|
||||
if f.u == strconv.single_minus_zero {
|
||||
return '-0'
|
||||
return '-0.'
|
||||
}
|
||||
if f.u == strconv.single_plus_zero {
|
||||
return '0'
|
||||
return '0.'
|
||||
}
|
||||
}
|
||||
abs_x := f32_abs(x)
|
||||
@ -103,11 +103,11 @@ pub fn (x f32) str() string {
|
||||
[inline]
|
||||
pub fn (x f32) strg() string {
|
||||
if x == 0 {
|
||||
return '0'
|
||||
return '0.0'
|
||||
}
|
||||
abs_x := f32_abs(x)
|
||||
if abs_x >= 0.0001 && abs_x < 1.0e6 {
|
||||
return strconv.f32_to_str_l_no_dot(x)
|
||||
return strconv.f32_to_str_l_with_dot(x)
|
||||
} else {
|
||||
return strconv.ftoa_32(x)
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ fn test_map_of_f32() {
|
||||
mut m32 := map[f32]string{}
|
||||
m32[1.0] = 'one'
|
||||
println(m32)
|
||||
assert '$m32' == r"{1.: 'one'}"
|
||||
assert '$m32' == r"{1.0: 'one'}"
|
||||
for k, v in m32 {
|
||||
assert typeof(k).name == 'f32'
|
||||
assert typeof(v).name == 'string'
|
||||
@ -17,7 +17,7 @@ fn test_map_of_f64() {
|
||||
}
|
||||
m64[1.0] = 'one'
|
||||
println(m64)
|
||||
assert '$m64' == r"{3.14: 'pi', 1.: 'one'}"
|
||||
assert '$m64' == r"{3.14: 'pi', 1.0: 'one'}"
|
||||
for k, v in m64 {
|
||||
assert typeof(k).name == 'f64'
|
||||
assert typeof(v).name == 'string'
|
||||
|
@ -190,11 +190,11 @@ fn test_signed_cast() {
|
||||
mut u := strconv.Float64u{
|
||||
u: strconv.double_plus_zero
|
||||
}
|
||||
assert '${u.f:g}' == '0'
|
||||
assert '${u.f:G}' == '0'
|
||||
assert '${u.f:g}' == '0.0'
|
||||
assert '${u.f:G}' == '0.0'
|
||||
u.u = strconv.double_minus_zero
|
||||
assert '${u.f:g}' == '0'
|
||||
assert '${u.f:G}' == '0'
|
||||
assert '${u.f:g}' == '0.0'
|
||||
assert '${u.f:G}' == '0.0'
|
||||
u.u = strconv.double_plus_infinity
|
||||
assert '${u.f:g}' == '+inf'
|
||||
assert '${u.f:G}' == '+INF'
|
||||
@ -206,11 +206,11 @@ fn test_signed_cast() {
|
||||
mut u := strconv.Float32u{
|
||||
u: strconv.single_plus_zero
|
||||
}
|
||||
assert '${u.f:g}' == '0'
|
||||
assert '${u.f:G}' == '0'
|
||||
assert '${u.f:g}' == '0.0'
|
||||
assert '${u.f:G}' == '0.0'
|
||||
u.u = strconv.single_minus_zero
|
||||
assert '${u.f:g}' == '0'
|
||||
assert '${u.f:G}' == '0'
|
||||
assert '${u.f:g}' == '0.0'
|
||||
assert '${u.f:G}' == '0.0'
|
||||
u.u = strconv.single_plus_infinity
|
||||
assert '${u.f:g}' == '+inf'
|
||||
assert '${u.f:G}' == '+INF'
|
||||
|
@ -425,7 +425,7 @@ fn test_abs_zero() {
|
||||
|
||||
ret2 := abs(0.0)
|
||||
println(ret2)
|
||||
assert '$ret2' == '0'
|
||||
assert '$ret2' == '0.0'
|
||||
}
|
||||
|
||||
fn test_floor() {
|
||||
|
@ -138,7 +138,7 @@ fn test_float_to_str() {
|
||||
|
||||
// test f32
|
||||
for c, x in test_cases_f32 {
|
||||
println(x)
|
||||
// println(x)
|
||||
s := strconv.f32_to_str(x, 8)
|
||||
s1 := exp_result_f32[c]
|
||||
// println("$s1 $s")
|
||||
@ -154,10 +154,13 @@ fn test_float_to_str() {
|
||||
}
|
||||
|
||||
// test long format
|
||||
for exp := 1; exp < 120; exp++ {
|
||||
assert strconv.f64_to_str_l('1e1'.f64()).len == 4 // '10.0'
|
||||
assert strconv.f64_to_str_l('1e-1'.f64()).len == 3 // '0.1'
|
||||
|
||||
for exp := 2; exp < 120; exp++ {
|
||||
a := strconv.f64_to_str_l(('1e' + exp.str()).f64())
|
||||
// println(a)
|
||||
assert a.len == exp + 1
|
||||
assert a.len == exp + 3
|
||||
|
||||
b := strconv.f64_to_str_l(('1e-' + exp.str()).f64())
|
||||
// println(b)
|
||||
|
@ -36,14 +36,14 @@ pub fn f32_to_str_l(f f32) string {
|
||||
return res
|
||||
}
|
||||
|
||||
// f32_to_str_l_no_dot returns `f` as a `string` in decimal notation with a maximum of 6 digits after the dot.
|
||||
// The decimal digits after the dot can be omitted.
|
||||
// f32_to_str_l_with_dot returns `f` as a `string` in decimal notation with a maximum of 6 digits after the dot.
|
||||
// If the decimal digits after the dot are zero, a '.0' is appended for clarity.
|
||||
//
|
||||
// Example: assert strconv.f32_to_str_l_no_dot(34.) == '34'
|
||||
// Example: assert strconv.f32_to_str_l_with_dot(34.) == '34.0'
|
||||
[manualfree]
|
||||
pub fn f32_to_str_l_no_dot(f f32) string {
|
||||
pub fn f32_to_str_l_with_dot(f f32) string {
|
||||
s := f32_to_str(f, 6)
|
||||
res := fxx_to_str_l_parse_no_dot(s)
|
||||
res := fxx_to_str_l_parse_with_dot(s)
|
||||
unsafe { s.free() }
|
||||
return res
|
||||
}
|
||||
@ -59,14 +59,14 @@ pub fn f64_to_str_l(f f64) string {
|
||||
return res
|
||||
}
|
||||
|
||||
// f64_to_str_l_no_dot returns `f` as a `string` in decimal notation with a maximum of 18 digits after the dot.
|
||||
// The decimal digits after the dot can be omitted.
|
||||
// f64_to_str_l_with_dot returns `f` as a `string` in decimal notation with a maximum of 18 digits after the dot.
|
||||
// If the decimal digits after the dot are zero, a '.0' is appended for clarity.
|
||||
//
|
||||
// Example: assert strconv.f64_to_str_l_no_dot (34.) == '34'
|
||||
// Example: assert strconv.f64_to_str_l_with_dot (34.) == '34.0'
|
||||
[manualfree]
|
||||
pub fn f64_to_str_l_no_dot(f f64) string {
|
||||
pub fn f64_to_str_l_with_dot(f f64) string {
|
||||
s := f64_to_str(f, 18)
|
||||
res := fxx_to_str_l_parse_no_dot(s)
|
||||
res := fxx_to_str_l_parse_with_dot(s)
|
||||
unsafe { s.free() }
|
||||
return res
|
||||
}
|
||||
@ -187,23 +187,30 @@ pub fn fxx_to_str_l_parse(s string) string {
|
||||
i++
|
||||
}
|
||||
}
|
||||
/*
|
||||
// remove the dot form the numbers like 2.
|
||||
|
||||
// Add a zero after the dot from the numbers like 2.
|
||||
if r_i > 1 && res[r_i - 1] == `.` {
|
||||
r_i--
|
||||
res[r_i] = `0`
|
||||
r_i++
|
||||
} else if `.` !in res {
|
||||
// If there is no dot, add it with a zero
|
||||
res[r_i] = `.`
|
||||
r_i++
|
||||
res[r_i] = `0`
|
||||
r_i++
|
||||
}
|
||||
*/
|
||||
|
||||
res[r_i] = 0
|
||||
return unsafe { tos(res.data, r_i) }
|
||||
}
|
||||
|
||||
// fxx_to_str_l_parse_no_dot returns a `string` in decimal notation converted from a
|
||||
// fxx_to_str_l_parse_with_dot returns a `string` in decimal notation converted from a
|
||||
// floating-point `string` in scientific notation.
|
||||
// The decimal digits after the dot can be omitted.
|
||||
// If the decimal digits after the dot are zero, a '.0' is appended for clarity.
|
||||
//
|
||||
// Example: assert strconv.fxx_to_str_l_parse_no_dot ('34.e+01') == '340'
|
||||
// Example: assert strconv.fxx_to_str_l_parse_with_dot ('34.e+01') == '340.0'
|
||||
[direct_array_access; manualfree]
|
||||
pub fn fxx_to_str_l_parse_no_dot(s string) string {
|
||||
pub fn fxx_to_str_l_parse_with_dot(s string) string {
|
||||
// check for +inf -inf Nan
|
||||
if s.len > 2 && (s[0] == `n` || s[1] == `i`) {
|
||||
return s.clone()
|
||||
@ -315,9 +322,16 @@ pub fn fxx_to_str_l_parse_no_dot(s string) string {
|
||||
}
|
||||
}
|
||||
|
||||
// remove the dot form the numbers like 2.
|
||||
// Add a zero after the dot from the numbers like 2.
|
||||
if r_i > 1 && res[r_i - 1] == `.` {
|
||||
r_i--
|
||||
res[r_i] = `0`
|
||||
r_i++
|
||||
} else if `.` !in res {
|
||||
// If there is no dot, add it with a zero
|
||||
res[r_i] = `.`
|
||||
r_i++
|
||||
res[r_i] = `0`
|
||||
r_i++
|
||||
}
|
||||
|
||||
res[r_i] = 0
|
||||
|
@ -238,10 +238,16 @@ fn to_burntsushi(value ast.Value) string {
|
||||
}
|
||||
if !value.text.starts_with('0x')
|
||||
&& (value.text.contains('.') || value.text.to_lower().contains('e')) {
|
||||
mut val := '$value.f64()'.replace('.e+', '.0e') // json notation
|
||||
if !val.contains('.') && val != '0' { // json notation
|
||||
mut val := '$value.f64()'.replace('.e+', '.0e') // JSON notation
|
||||
if !val.contains('.') && val != '0' { // JSON notation
|
||||
val += '.0'
|
||||
}
|
||||
// Since https://github.com/vlang/v/pull/16079 V's string conversion of a zero (0) will
|
||||
// output "0.0" for float types - the JSON test suite data, however, expects "0" for floats
|
||||
// The following is a correction for that inconsistency
|
||||
if val == '0.0' {
|
||||
val = '0'
|
||||
}
|
||||
return '{ "type": "float", "value": "$val" }'
|
||||
}
|
||||
v := value.i64()
|
||||
|
@ -1,3 +1,3 @@
|
||||
[1, 0, 0]
|
||||
[0, 1, 0]
|
||||
[0, 0, 1]
|
||||
[1.0, 0.0, 0.0]
|
||||
[0.0, 1.0, 0.0]
|
||||
[0.0, 0.0, 1.0]
|
@ -14,5 +14,5 @@ fn test_assign_map_value_of_fixed_array() {
|
||||
|
||||
arr = m['C']
|
||||
println(arr)
|
||||
assert '$arr' == '[0, 0]'
|
||||
assert '$arr' == '[0.0, 0.0]'
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ fn test_fixed_array_const_size() {
|
||||
fn test_fixed_array_const_u64_size() {
|
||||
a := [2 * u64_size]f64{}
|
||||
println(a)
|
||||
assert '$a' == '[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]'
|
||||
assert '$a' == '[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]'
|
||||
}
|
||||
|
||||
const n = u64(5_000)
|
||||
|
@ -1,6 +1,6 @@
|
||||
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:30] mi.in_(): 1.
|
||||
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:31] mi.out(): 2.
|
||||
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:36] in_put.in_(): 1.
|
||||
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:37] in_put.out(): 2.
|
||||
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:39] in_put.in_(): 1.
|
||||
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:40] in_put.out(): 2.
|
||||
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:30] mi.in_(): 1.0
|
||||
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:31] mi.out(): 2.0
|
||||
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:36] in_put.in_(): 1.0
|
||||
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:37] in_put.out(): 2.0
|
||||
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:39] in_put.in_(): 1.0
|
||||
[vlib/v/tests/inout/dump_generic_interface_ref_arg.vv:40] in_put.out(): 2.0
|
||||
|
@ -1,12 +1,12 @@
|
||||
[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:19] '$T.name $input': int 1
|
||||
[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:26] '$T.name $input': int 1
|
||||
[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:36] next(1): 0
|
||||
[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:19] '$T.name $input': f64 1.
|
||||
[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:26] '$T.name $input': f64 1.
|
||||
[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:37] next(1.0): 64.
|
||||
[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:36] next(1): 0.0
|
||||
[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:19] '$T.name $input': f64 1.0
|
||||
[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:26] '$T.name $input': f64 1.0
|
||||
[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:37] next(1.0): 64.0
|
||||
[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:19] '$T.name $input': f64 11.1
|
||||
[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:26] '$T.name $input': f64 11.1
|
||||
[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:38] next(11.1): 64.
|
||||
[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:38] next(11.1): 64.0
|
||||
[vlib/v/tests/inout/dump_nested_generic_fn_call_ref_arg.vv:15] '$T.name $input': Score Score{
|
||||
ave: 23.4
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
Point(Quad{
|
||||
x: 1
|
||||
y: 2
|
||||
z: 3
|
||||
w: 1
|
||||
x: 1.0
|
||||
y: 2.0
|
||||
z: 3.0
|
||||
w: 1.0
|
||||
})
|
||||
|
@ -9,7 +9,7 @@ fn test_empty_interface_string_interpolation() {
|
||||
b := IEmpty(f32(1))
|
||||
c := IEmpty(Abc{'abc'})
|
||||
assert '$a' == 'IEmpty(1)'
|
||||
assert '$b' == 'IEmpty(1.)'
|
||||
assert '$b' == 'IEmpty(1.0)'
|
||||
assert '$c'.starts_with('IEmpty(Abc{')
|
||||
assert '$c'.contains("x: 'abc'")
|
||||
assert '$c'.ends_with('})')
|
||||
|
@ -13,15 +13,15 @@ fn test_variadic_array_decompose() {
|
||||
a << Foo{}
|
||||
|
||||
input := [0.0, 1.0]
|
||||
assert a[0].method(...input) == '[0, 1]'
|
||||
assert a[0].method(...[0.0, 1.0]) == '[0, 1]'
|
||||
assert a[0].method(...input) == '[0.0, 1.0]'
|
||||
assert a[0].method(...[0.0, 1.0]) == '[0.0, 1.0]'
|
||||
}
|
||||
|
||||
fn test_variadic_multiple_args() {
|
||||
mut a := []Element{}
|
||||
a << Foo{}
|
||||
|
||||
assert a[0].method(0.0, 1.0) == '[0, 1]'
|
||||
assert a[0].method(0.0, 1.0) == '[0.0, 1.0]'
|
||||
}
|
||||
|
||||
interface Animal {}
|
||||
|
@ -23,7 +23,7 @@ fn test_float_lit_call_method() {
|
||||
x5 := 2.e-3.str()
|
||||
assert x5 == '0.002'
|
||||
x6 := 5.0.str()
|
||||
assert x6 == '5.'
|
||||
assert x6 == '5.0'
|
||||
// x7 := 5..str() Syntax `5.` is allowed, but do not call method on it (`5..str()` is parsed as a range). Use `5.0.str()` instead.
|
||||
x8 := 7.345e-7.str()
|
||||
assert x8 == '7.345e-07'
|
||||
|
@ -1 +1 @@
|
||||
0
|
||||
0.0
|
||||
|
@ -1 +1 @@
|
||||
0
|
||||
0.0
|
||||
|
@ -30,7 +30,7 @@ fn test_fixed_array_struct_string_interpolation() {
|
||||
ctx.vb = [1.1, x, 3.3, 4.4, 5.0, 6.0, 7.0, 8.9]!
|
||||
s := '$ctx'
|
||||
assert s.starts_with('Context{')
|
||||
assert s.contains('vb: [1.1, 2.32, 3.3, 4.4, 5, 6, 7, 8.9]')
|
||||
assert s.contains('vb: [1.1, 2.32, 3.3, 4.4, 5.0, 6.0, 7.0, 8.9]')
|
||||
assert s.ends_with('}')
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ fn test_typeof_on_sumtypes() {
|
||||
assert typeof(c).name == 'MySumType'
|
||||
|
||||
assert a.str() == '32'
|
||||
assert b.str() == '123.'
|
||||
assert b.str() == '123.0'
|
||||
assert c.str() == 'FooBar'
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user