nanoframework / Home

:house: The landing page for .NET nanoFramework repositories.
https://www.nanoframework.net
MIT License
844 stars 75 forks source link

Double to string conversion problem #1484

Open MateuszKlatecki opened 1 month ago

MateuszKlatecki commented 1 month ago

Target name(s)

ALL

Firmware version

newest

Was working before? On which version?

I think it worked better a year ago

Device capabilities

No response

Description

Converting double to string does not work properly. For example, 14 is converted to 13.999999999999999, 92 to 91.999999999999993.

I am aware of how floating point numbers work and that some cannot be written without error, but the numbers 14 or 92 are not like that.

How to reproduce

Run this program:

using System;

namespace DoubleToStringTest
{
    public class Program
    {
        public static void Main()
        {
            for (int i = 0; i < 100; i++)
            {
                double d = i;
                Console.WriteLine($"{i} {d}");
            }
        }
    }
}

Program prints:

0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
11 11
12 12
13 13
14 13.999999999999999
15 15
16 16
17 17
18 18
19 19
20 20
21 21
22 22
23 22.999999999999998
24 23.999999999999999
25 25
26 26
27 27
28 27.999999999999998
29 29
30 30
31 31
32 32
33 32.999999999999998
34 33.999999999999999
35 35
36 36
37 37
38 37.999999999999998
39 39
40 40
41 40.999999999999996
42 42
43 42.999999999999998
44 44
45 45
46 45.999999999999996
47 47
48 47.999999999999998
49 49
50 50
51 50.999999999999996
52 52
53 52.999999999999998
54 54
55 55
56 55.999999999999996
57 57
58 57.999999999999998
59 59
60 60
61 60.999999999999996
62 62
63 62.999999999999998
64 64
65 65
66 65.999999999999996
67 67
68 67.999999999999998
69 69
70 70
71 70.999999999999996
72 72
73 72.999999999999998
74 74
75 75
76 75.999999999999996
77 77
78 77.999999999999998
79 79
80 80
81 80.999999999999996
82 81.999999999999993
83 83
84 84
85 85
86 85.999999999999996
87 86.999999999999993
88 88
89 89
90 90
91 90.999999999999996
92 91.999999999999993
93 93
94 94
95 95
96 95.999999999999996
97 96.999999999999993
98 98
99 99

Expected behaviour

Program should print:

0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
11 11
12 12
13 13
14 14
15 15
16 16
17 17
18 18
19 19
20 20
21 21
22 22
23 23
24 24
25 25
26 26
27 27
28 28
29 29
30 30
31 31
32 32
33 33
34 34
35 35
36 36
37 37
38 38
39 39
40 40
41 41
42 42
43 43
44 44
45 45
46 46
47 47
48 48
49 49
50 50
51 51
52 52
53 53
54 54
55 55
56 56
57 57
58 58
59 59
60 60
61 61
62 62
63 63
64 64
65 65
66 66
67 67
68 68
69 69
70 70
71 71
72 72
73 73
74 74
75 75
76 76
77 77
78 78
79 79
80 80
81 81
82 82
83 83
84 84
85 85
86 86
87 87
88 88
89 89
90 90
91 91
92 92
93 93
94 94
95 95
96 96
97 97
98 98
99 99

Screenshots

No response

Aditional information

No response

CoryCharlton commented 1 month ago

This issue might be the similar to https://github.com/nanoframework/Home/issues/1401 where the double is being cast to a float and that causes a loss of precision.

Ellerbach commented 1 month ago

Duplicate with #1429 See that specific issue for the answer. I will close this issue.

MateuszKlatecki commented 1 month ago

@Ellerbach I must disagree that this is not a bug. While it is understood that floating-point arithmetic can introduce small errors due to the way numbers are represented in binary, the numbers 14 and 92 can be exactly represented in the IEEE 754 standard used for floating-point arithmetic. Therefore, when converted to a string, they should retain their exact integer representation without any introduced imprecision.

Even (as you wrote) less smart languages like Python can deal with the numbers 14 or 92 but nanoFramework not.

Another thing that makes something wrong is that this code

double d = 14d;
Console.WriteLine($"{d}");

will print 13.999999999999999 and the use of float, a less precise variable,

float f = 14f;
Console.WriteLine($"{f}");

already works properly

Additionally, I looked around the code and there is even a test that checks this https://github.com/nanoframework/CoreLibrary/blob/main/Tests/NFUnitTestArithmetic/UnitTestFormat.cs#L189 but the selected number in the test does not cause a problem. Replacing -1234 with -14 would cause this test to fail.

Ellerbach commented 1 month ago

OK, reopening the issue. That say, it depends of the device precision. Double is always available, but if not natively supported, will automatically fall back to float.

josesimoes commented 1 month ago

Actually, that's the other way around: float is always available. Double is natively supported if the platform has DP hardware support (or emulated). Rational for this is explained in our docs here