REBOL3 tracker
  0.9.12 beta
Ticket #0000729 User: anonymous

Project:



rss
TypeBug Statuscomplete Date28-Apr-2009 09:32
Versionalpha 49 CategoryUnspecified Submitted byLadislav
PlatformLinux x86 libc6 Severityminor Prioritynormal

Summary MOLD and DECIMAL-DIGITS
Description As far as I remember, the system/options/decimal-digits option was defined to make sure that if we set:

system/options/decimal-digits: 17

, for any decimal number X would hold:

x - load mold x == 0.0

This is no longer the case, as the example below shows.

This influences the orthogonality of LOAD and MOLD and invalidates the documentation article about decimals.
Example code
x: 0.30000000000000004 
system/options/decimal-digits: 17 
same? x load mold x ; == false (should be true) 

Assigned ton/a Fixed inr3 master Last Update19-Sep-2013 14:35


Comments
(0000565)
BrianH
28-Apr-2009 17:29

The example doesn't show anything we can test. Try providing a specific number for x that has the problem you mention - the only number in the example doesn't have the problem.

In alpha 49:
>> system/options/decimal-digits: 17
== 17
>> x: 5.5511151231257827e-017
== 5.5511151231257827e-017
>> x - load mold x
== 0.0
(0000567)
Ladislav
29-Apr-2009 07:57

example updated, sorry for the omission
(0000595)
BrianH
29-Apr-2009 21:02

Carl, I think that in his example false was supposed to be an error. I'm not sure whether 17 digits is sufficient to show the rounding error in 0.1 + 0.1 + 0.1. The error in question is unchanged between alpha 49 and 50.

In any case, the point he is making is that 0.1 + 0.1 + 0.1 has a rounding error that isn't shown by MOLD of that value, no matter what the setting for system/options/decimal-digits is. I've changed the ticket accordingly.
(0000596)
BrianH
29-Apr-2009 21:50

This rounding error is a known problem with IEEE754-style binary floating point calculations, so people would expect this to be an error, and probably wouldn't want to see it.

What I think Ladislav is proposing, the system/options/decimal-digits: 17 method:

>> system/options/decimal-digits: 17
>> zero? (0.1 + 0.1 + 0.1) - load mold (0.1 + 0.1 + 0.1)
== true

I'm not sure that this is a good idea to fix the way Ladislav is suggesting. Options like decimal-digits and binary-base can affect the behavior of REBOL functions in hidden ways. These options even existing means that you have to check them before every operation that they affect. Plus, that 17 is a magic number, and one that could change if we switched to a larger floating point representation for decimal! values. The option would have to be task-local as well.

At the root of this is the idea that LOAD MOLD of a value will generate the same value. This is not the case for many values: MOLD generates approximate REBOL source, not literal representations of REBOL values. The opposite of MOLD is DO, not LOAD, and you don't necessarily get the same result even then.

Literal representations of REBOL values are generated by MOLD/all, not MOLD. Aside from binding issues, in theory LOAD MOLD/all of a value should be equal to the value. If this isn't the case for a given value, this should be considered an error in MOLD/all for that datatype. If it is possible to generate values of a datatype that can't be represented in REBOL source, there needs to be a serialized syntax to represent that value that can be generated by MOLD/all (there is such an error for the word! type).

Here's my suggestion, the MOLD/all method:

>> zero? (0.1 + 0.1 + 0.1) - load mold (0.1 + 0.1 + 0.1)
== false
>> zero? (0.1 + 0.1 + 0.1) - load mold/all (0.1 + 0.1 + 0.1)
== true

MOLD would generate a nice representation of the value, ignoring the rounding error. Perhaps system/options/decimal-digits would affect what MOLD would consider a rounding error.

MOLD/all would ignore any decimal-digits option and generate all of the digits necessary to exactly recreate the same value in memory, assuming that the decimal! is internally represented by a floating point value of the same size and format. If necessary, have it generate a serialized "#[decimal! #{hex digits}]" syntax. It's the only way to be sure.
(0000604)
Ladislav
30-Apr-2009 10:23

A terminological point:

Brian uses a notion of "rounding error". This is quite unfortunate terminology, since every floating point value X exactly (i.e. without any "rounding error") represents itself.

The only case when a rounding error is involved is, when a number that is not exactly representable as a floating point value is represented by a floating point value.

Because of the above, for any given floating point value it is *impossible* to find out whether it "has a rounding error" or not. The same holds above: what if my goal was to obtain *exactly* the value I obtained? If that is true, then the value *does not have* any rounding error.
(0000605)
Ladislav
30-Apr-2009 10:38

I am strongly *against* Brian's suggestion to have:

zero? x - load mold x == false

for *every* value of system/options/decimal-digits.

Why isn't it better to represent the given floating point number as precisely as requested by the user?

It is provable that every 64-bit IEEE754 binary floating point number is *accurately* representable (meaning, that load mold x produces x) by a 17-digit E representation.

Nevertheless, I support Brian's point with mold/all, meaning that mold/all should always (independently on system/options/decimal-digits) work so, that for every floating point value X:

zero? x - load mold/all x ; == true
(0000607)
Carl
30-Apr-2009 16:27

There are several issues. We can only solve these issues if we define the precise programming situations we want to support, write tests to verify those, and then modify R3 to produce those results. IFAIK, that's the only way to deal with these floating point issues.

For example, a "professional programmer" may not want R3 to do any modifications of the IEEE fp values. The programmer already knows the behavior, and will deal with it.

But, a beginner (say a student) who adds a few numbers, does not want to see a crazy result (although, in some cases, it may not be prevented, this is float after all, and it is the reason we also support precision math separately.)

Then, there's the rest of us, who want to get the job done, and we know that float is an "approximate value", so before we store or display it, we use ROUND to adjust for the correct result.

I should also point out, that however "accurate" the string representation of the number, as the number is parsed and converted from chars to its IEEE internal format, various small "truncations" (to avoid the word "round") might occur. After all, the number does not magically get converted, we must process it using C code, with multiply and add, etc.

Therefore, perhaps what BrianH has suggested is a good idea: to allow a hex mold/all representation of the number, the precise bits that are in memory. I believe that format guarantees that the stored form will recreate the precise value that was saved (molded).
(0000608)
BrianH
30-Apr-2009 17:56

Ladislav, it is provable that a 64bit IEEE754 floating point number can be representable in 17 digits, true.

It is *not* provable that the (possibly future) version of REBOL that is loading the value will implement decimal! using 64bit floating point values - perhaps it will use 128bit values. Who knows? It is definitely provable most developers will not know what the 17 means either, and that the number 17 is not included when the decimal is molded.

That's why I referred to the 17 as a magic number.

With a hex MOLD/all representation you could statically determine that the original number was 64bit, just by its length, no questions. I had been leaning toward just doing a serialized representation when you need to, but with Carl's post above I am leaning towards doing it with every MOLD/all.
(0000915)
Ladislav
9-Jun-2009 14:27

Ticket #897 added to reflect the requirement to use DECIMAL-DIGITS = 17 for MOLD/ALL
(0000920)
BrianH
10-Jun-2009 02:11

As of alpha 56 system/options/decimal-digits works. A separate ticket will be created to request that this option be moved to a MOLD argument.
(0002890)
Ladislav
18-Nov-2010 08:32

In the core-tests suite.
(0003392)
Ladislav
22-Jan-2013 08:55

After the #1939 has been built by Carl I consider this ticket built.

Date User Field Action Change
19-Sep-2013 14:35 Ladislav Status Modified built => complete
22-Jan-2013 21:15 BrianH Fixedin Modified alpha 56 => r3 master
22-Jan-2013 08:55 Ladislav Comment : 0003392 Added -
22-Jan-2013 08:54 Ladislav Status Modified pending => built
20-Jan-2013 18:22 Ladislav Comment : 0000604 Modified -
20-Jan-2013 01:13 Ladislav Comment : 0000615 Removed -
20-Jan-2013 00:00 Ladislav Code Modified -
19-Jan-2013 23:59 Ladislav Comment : 0002891 Removed -
19-Jan-2013 23:59 Ladislav Comment : 0003377 Removed -
19-Jan-2013 23:47 Ladislav Comment : 0003377 Added -
19-Jan-2013 23:43 Ladislav Comment : 0000605 Modified -
19-Jan-2013 23:40 Ladislav Comment : 0000605 Modified -
19-Jan-2013 23:38 Ladislav Comment : 0000604 Modified -
19-Jan-2013 23:36 Ladislav Comment : 0000604 Modified -
19-Jan-2013 23:35 Ladislav Description Modified -
18-Nov-2010 08:33 Ladislav Comment : 0002891 Added -
18-Nov-2010 08:32 Ladislav Comment : 0002890 Added -
18-Nov-2010 08:32 Ladislav Platform Modified All => Linux x86 libc6
18-Nov-2010 08:32 Ladislav Status Modified tested => pending
18-Nov-2010 08:32 Ladislav Category Modified => Unspecified
10-Jun-2009 02:11 BrianH Comment : 0000920 Added -
10-Jun-2009 02:08 BrianH Status Modified reviewed => tested
10-Jun-2009 02:08 BrianH Fixedin Modified => alpha 56
9-Jun-2009 14:27 Ladislav Comment : 0000915 Added -
3-May-2009 10:40 Ladislav Comment : 0000615 Added -
30-Apr-2009 18:08 BrianH Comment : 0000608 Modified -
30-Apr-2009 17:56 BrianH Comment : 0000608 Added -
30-Apr-2009 16:27 carl Comment : 0000607 Added -
30-Apr-2009 10:38 Ladislav Comment : 0000605 Added -
30-Apr-2009 10:23 Ladislav Comment : 0000604 Added -
30-Apr-2009 00:28 BrianH Code Modified -
30-Apr-2009 00:26 BrianH Code Modified -
29-Apr-2009 21:50 BrianH Comment : 0000596 Added -
29-Apr-2009 21:23 BrianH Comment : 0000595 Modified -
29-Apr-2009 21:11 BrianH Status Modified built => reviewed
29-Apr-2009 21:11 BrianH Fixedin Modified alpha 50 => none
29-Apr-2009 21:11 BrianH Code Modified -
29-Apr-2009 21:02 BrianH Comment : 0000595 Added -
29-Apr-2009 15:59 carl Status Modified submitted => built
29-Apr-2009 15:59 carl Fixedin Modified => alpha 50
29-Apr-2009 13:26 Ladislav Status Modified problem => submitted
29-Apr-2009 07:58 Ladislav Code Modified -
29-Apr-2009 07:58 Ladislav Code Modified -
29-Apr-2009 07:57 Ladislav Comment : 0000567 Added -
29-Apr-2009 07:55 Ladislav Comment : 0000566 Removed -
29-Apr-2009 07:53 Ladislav Comment : 0000566 Added -
28-Apr-2009 17:30 BrianH Status Modified submitted => problem
28-Apr-2009 17:29 BrianH Status Modified problem => submitted
28-Apr-2009 17:29 BrianH Comment : 0000565 Added -
28-Apr-2009 17:26 BrianH Status Modified submitted => problem
28-Apr-2009 17:26 BrianH Code Modified -
28-Apr-2009 17:26 BrianH Description Modified -
28-Apr-2009 09:32 Ladislav Ticket Added -