Hello,
I would like to hear your opinion. In VO we normally used float for all floating numbers.
Our experience was that sometimes it was nice to have an automatic formatting according to assumed decimals, and
sometimes it provoked undesired rounding errors. Having the standard system/GUIclasses it was also often the best way to interact with usuals.
In our own transporter to X# we inserted a conversion to Real8 for all float variables because there were suggestions in the past to do this for performance reasons and thinking to get rid of old VO variable types.
Now we have doubts about doing this. On one hand we have much old code where we did not pay attention at formatting using ntrim or Str without decimal parameters. Also usuals seem to be related to float very much. On the other hand there were proposals to use the type "decimal" to have a higher precision.
Float, Real8, or Decimal?
- ArneOrtlinghaus
- Posts: 412
- Joined: Tue Nov 10, 2015 7:48 am
- Location: Italy
Float, Real8, or Decimal?
Hello Arne,
On comp.lang there's a discussion starting with "Very interesting: XSharp development roadmap" starting 2-5-2018. Within the thread the so called decimal datatype was discussed; Chris added some code where rounding differences were absent using this datatype.
Otherwise, this discussion can be found in comp.lang multiple times since 2000 with different winners. I've chosen FLOAT everywhere based on one of those discussions. I "tricked" the rounding error sufficiently with NTRIM but if I would start replacing code converted from VO to X# this decimal type is of course a better solution.
Dick
On comp.lang there's a discussion starting with "Very interesting: XSharp development roadmap" starting 2-5-2018. Within the thread the so called decimal datatype was discussed; Chris added some code where rounding differences were absent using this datatype.
Otherwise, this discussion can be found in comp.lang multiple times since 2000 with different winners. I've chosen FLOAT everywhere based on one of those discussions. I "tricked" the rounding error sufficiently with NTRIM but if I would start replacing code converted from VO to X# this decimal type is of course a better solution.
Dick
Float, Real8, or Decimal?
Hi Arne,
the decimal datatype for me is motivation enough to move to X#, and both Robert and Chris have confirmed that the X# runtime internally uses the decimal datatype for usuals, so goodbye rounding problems.
After migrating my VO applications, I will change all occurrences of floats to decimals.
So my answer to your question should be clear <g>.
Wolfgang
the decimal datatype for me is motivation enough to move to X#, and both Robert and Chris have confirmed that the X# runtime internally uses the decimal datatype for usuals, so goodbye rounding problems.
After migrating my VO applications, I will change all occurrences of floats to decimals.
So my answer to your question should be clear <g>.
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
-
- Posts: 774
- Joined: Wed May 17, 2017 8:50 am
- Location: Germany
Float, Real8, or Decimal?
Hi Arne,
the only reason why the VO-Datatypes REAL4 ( single) and REAL8 ( double ) exist is to have the possiblity to talk with foreign hosted systems ( typically C / Winapi Dlls ) There´s absolutly no reason to use them with plain VO code. So, when switching to X#, i would keep at the beginning the floats and switch step by step to decimals. In german words: "Nicht zuviele Baustellen gleichzeitig eröffnen" . To workaround the known float rounding problems i´m using since ages this function.
FUNCTION Runde ( fVal AS FLOAT , iDeci AS INT ) AS FLOAT PASCAL
RETURN Round (fVal + ( 1 / 10 ^ 10 ), iDeci )
regards
Karl-Heinz
the only reason why the VO-Datatypes REAL4 ( single) and REAL8 ( double ) exist is to have the possiblity to talk with foreign hosted systems ( typically C / Winapi Dlls ) There´s absolutly no reason to use them with plain VO code. So, when switching to X#, i would keep at the beginning the floats and switch step by step to decimals. In german words: "Nicht zuviele Baustellen gleichzeitig eröffnen" . To workaround the known float rounding problems i´m using since ages this function.
FUNCTION Runde ( fVal AS FLOAT , iDeci AS INT ) AS FLOAT PASCAL
RETURN Round (fVal + ( 1 / 10 ^ 10 ), iDeci )
regards
Karl-Heinz
Float, Real8, or Decimal?
Karl-Heinz,
> There´s absolutly no reason to use them with plain VO code.
oh, there is! In VO floats are dynamic objects and therefor subject to be garbage collected.
Regards
Meinhard
> There´s absolutly no reason to use them with plain VO code.
oh, there is! In VO floats are dynamic objects and therefor subject to be garbage collected.
Regards
Meinhard
Float, Real8, or Decimal?
Meinhard,
You are right. They are dynamic. And in older versions of VO there was a compiler problem with Floats that could cause corruption and 5333s.
However having said that: I have seen many examples where people followed the advise given on newsgroups and forums and changed all their floats to real8s. And then they were calling late bound function or method calls passing these real8 values as parameter. And guess what: these real8 values are then converted to floats because USUAL does not support Real8.
My point is: you and I we know what we are doing. Many people don't know these details and blindly follow advises even in situations where it is useless and end up doing things the wrong way.
I have learned to be careful with advises like "thy shall not use floats because floats are evil".
So I tend to follow Karl-Heinz his advise in many cases.
Robert
You are right. They are dynamic. And in older versions of VO there was a compiler problem with Floats that could cause corruption and 5333s.
However having said that: I have seen many examples where people followed the advise given on newsgroups and forums and changed all their floats to real8s. And then they were calling late bound function or method calls passing these real8 values as parameter. And guess what: these real8 values are then converted to floats because USUAL does not support Real8.
My point is: you and I we know what we are doing. Many people don't know these details and blindly follow advises even in situations where it is useless and end up doing things the wrong way.
I have learned to be careful with advises like "thy shall not use floats because floats are evil".
So I tend to follow Karl-Heinz his advise in many cases.
Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
The Netherlands
robert@xsharp.eu
Float, Real8, or Decimal?
Hello Robert,
9-9-2000 Use Real
11-12-2000 Use Float
9-1-2001 Use Float.
And so on. In the latter discussion I added that using floats was CA recommended. And this is the reply from a certain Robert v.d. Hulst - on a reply of Geoff - I'd say: enjoy!
> Perhaps if you attended a VO conference somewhere you could catch up on
> these issues. Frew (whose 'proper' name is Angswillie) was quite specific
> about the use of the REALs as being compatibility data types and you even
> seem to agree with this point. But I need to correct the record you seem
> hell-bent on breaking every 5 mins, REAL4 and REAL8 are converted to a FLOAT
> internally and hence they are actually LESS effecient than floats. Given
> that you might save a few precious bytes per variable in static memory,
> reals still cause dynamic memory usage so you are saving nothing.
I agree with you: all the intermediate results of Floating Point calculations
are handled as Float variables. That is exactly what FRU (thai is his real
name) said at the Vo conference.
And if you are using variables of type Real4/Real8 the compiler converts the
intermediate results back into Real4/8 after the calculation is finished.
For Real8 the conversion is painless, since it only involves removing the
formatting information of a float (a float is not more than a real8 with
formatting information stored in dynamic memory) but for a Real4 the
conversion will mean losing some accuracy.
Dick
Not even blindly. Much of the discussion contained good arguments. If I search my "Agent" for comp.lang...Many people don't know these details and blindly follow advises even in situations where it is useless and end up doing things the wrong way.
9-9-2000 Use Real
11-12-2000 Use Float
9-1-2001 Use Float.
And so on. In the latter discussion I added that using floats was CA recommended. And this is the reply from a certain Robert v.d. Hulst - on a reply of Geoff - I'd say: enjoy!
> Perhaps if you attended a VO conference somewhere you could catch up on
> these issues. Frew (whose 'proper' name is Angswillie) was quite specific
> about the use of the REALs as being compatibility data types and you even
> seem to agree with this point. But I need to correct the record you seem
> hell-bent on breaking every 5 mins, REAL4 and REAL8 are converted to a FLOAT
> internally and hence they are actually LESS effecient than floats. Given
> that you might save a few precious bytes per variable in static memory,
> reals still cause dynamic memory usage so you are saving nothing.
I agree with you: all the intermediate results of Floating Point calculations
are handled as Float variables. That is exactly what FRU (thai is his real
name) said at the Vo conference.
And if you are using variables of type Real4/Real8 the compiler converts the
intermediate results back into Real4/8 after the calculation is finished.
For Real8 the conversion is painless, since it only involves removing the
formatting information of a float (a float is not more than a real8 with
formatting information stored in dynamic memory) but for a Real4 the
conversion will mean losing some accuracy.
Dick
Float, Real8, or Decimal?
Hmm, I think we need to use some specific code samples to make sure we are talking about the same thing. It's been a very long time I checked what VO does internally, but are you guys saying that in this sample there's internal conversion to FLOAT for every calculation in VO?:
LOCAL r1,r2 AS REAL8
r1 := 1.2
r2 := r1 * 2 // not 2.0
r1 := r2 + r1
r2 := r1 * r2
From what I remember, only the first line involves a FLOAT, because "1.2" in VO is a FLOAT literal, so it needs to be "converted" to REAL8, in order to be assigned to a REAL8 local. But form then on, all the shown arithmetic is done purely with REAL8s and no FLOATs are involved anymore. Am I wrong?
Personally I got rid of many 5333s in VO by doing exactly that, replacing data types in intense calculations from FLOAT to REAL8.
Note to everybody: In X# and also in Vulcan, there's definitely no conversion to FLOAT at all for this code. Actually you can avoid even the one conversion from literal FLOAT to REAL8 in the first line, by disabling the compiler option "FLOAT decimal literals"
Some other remarks:
- In X# and vulcan, FLOAT is not a garbage collected type anymore, so it's not that "bad" at times as in VO. Still, REAL8 and REAL4 are faster, because there's no overhead involved when using them (FLOAT is a custom data type)
- In X# (not in vulcan), the USUAL type indeed supports the Decimal type, so if you put a Decimal value in a USUAL, then you get a Decimal out as well (in vulcan you get a FLOAT out). But that does not mean that USUALs _ALWAYS_ use the Decimal data type to store floating point numbers, if you assign a float or real8 value to a usual, then it will be stored as a FLOAT.
For example when reading numerics from DBF fields, the value will be stored in the USUAL return type of certain RDD functions like FieldGet() as a FLOAT, which is needed for VO compatibility, as only the FLOAT type includes formatting information.
-Regarding which is best to use, it all depends on the specific needs, so if you rely heavily on the formatting feature of FLOAT and do not intend to modify the code, then it's possible best to keep using FLOATs. A few things to have in mind (for x#):
-REAL8 is the fastest, Decimal is the slowest, FLOAT performance is in between. AS previously stated, this speed difference can be important, or it can be completely irrelevant, depending on the usage scenario. Usually in our apps performance is limited due to disk access (loading values from DBF files) and not on numeric calculations after loading them, so in such cases the speed of the datatype used has very little if any impact.
-Decimal does not suffer from precision lost, the others do.
-In X#, all three types are value types (structures, stored in the stack), so none of them involve GC activity when using them.
-In vulcan, the sizes of REAL8, FLOAT, Decimal in bytes are 8,16,16. In X# (with the X# runtime), those numbers are 8,12,16
LOCAL r1,r2 AS REAL8
r1 := 1.2
r2 := r1 * 2 // not 2.0
r1 := r2 + r1
r2 := r1 * r2
From what I remember, only the first line involves a FLOAT, because "1.2" in VO is a FLOAT literal, so it needs to be "converted" to REAL8, in order to be assigned to a REAL8 local. But form then on, all the shown arithmetic is done purely with REAL8s and no FLOATs are involved anymore. Am I wrong?
Personally I got rid of many 5333s in VO by doing exactly that, replacing data types in intense calculations from FLOAT to REAL8.
Note to everybody: In X# and also in Vulcan, there's definitely no conversion to FLOAT at all for this code. Actually you can avoid even the one conversion from literal FLOAT to REAL8 in the first line, by disabling the compiler option "FLOAT decimal literals"
Some other remarks:
- In X# and vulcan, FLOAT is not a garbage collected type anymore, so it's not that "bad" at times as in VO. Still, REAL8 and REAL4 are faster, because there's no overhead involved when using them (FLOAT is a custom data type)
- In X# (not in vulcan), the USUAL type indeed supports the Decimal type, so if you put a Decimal value in a USUAL, then you get a Decimal out as well (in vulcan you get a FLOAT out). But that does not mean that USUALs _ALWAYS_ use the Decimal data type to store floating point numbers, if you assign a float or real8 value to a usual, then it will be stored as a FLOAT.
For example when reading numerics from DBF fields, the value will be stored in the USUAL return type of certain RDD functions like FieldGet() as a FLOAT, which is needed for VO compatibility, as only the FLOAT type includes formatting information.
-Regarding which is best to use, it all depends on the specific needs, so if you rely heavily on the formatting feature of FLOAT and do not intend to modify the code, then it's possible best to keep using FLOATs. A few things to have in mind (for x#):
-REAL8 is the fastest, Decimal is the slowest, FLOAT performance is in between. AS previously stated, this speed difference can be important, or it can be completely irrelevant, depending on the usage scenario. Usually in our apps performance is limited due to disk access (loading values from DBF files) and not on numeric calculations after loading them, so in such cases the speed of the datatype used has very little if any impact.
-Decimal does not suffer from precision lost, the others do.
-In X#, all three types are value types (structures, stored in the stack), so none of them involve GC activity when using them.
-In vulcan, the sizes of REAL8, FLOAT, Decimal in bytes are 8,16,16. In X# (with the X# runtime), those numbers are 8,12,16
Chris Pyrgas
XSharp Development Team
chris(at)xsharp.eu
XSharp Development Team
chris(at)xsharp.eu
Float, Real8, or Decimal?
You are right that only the first line of code (in VO) involved a FLOAT. If you use REAL8 inside a function or method then it will be more efficient than FLOAT.Chris wrote:but are you guys saying that in this sample there's internal conversion to FLOAT for every calculation in VO?:
LOCAL r1,r2 AS REAL8
r1 := 1.2
r2 := r1 * 2 // not 2.0
r1 := r2 + r1
r2 := r1 * r2
From what I remember, only the first line involves a FLOAT, because "1.2" in VO is a FLOAT literal, so it needs to be "converted" to REAL8, in order to be assigned to a REAL8 local. But form then on, all the shown arithmetic is done purely with REAL8s and no FLOATs are involved anymore. Am I wrong?
The problem is that I have also seen code that does this:
Code: Select all
LOCAL r8 as REAL8
LOCAL cValue AS STRING
r8 := SomeCalculationThatReturnsAReal8()
cValue := Ntrim(r8) // <- this will create a FLOAT on the fly
Code: Select all
CLASS FOO
EXPORT MyValue as REAL8
Function Test
local oFoo AS OBJECT // or as USUAL
local cValue as STRING
local r8 as real8
oFoo := Foo{}
oFoo:MyValue := 10.0 // A FLOAT will be packaged in a USUAL and then IVarPut is called and after that the FLOAT is assigned to the REAL8
r8 := oFoo:MyValue // IVarGet() is called. This reads the Real8 and stores it as float in a usual. THen afterwards the float is assigned to the r8
Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
The Netherlands
robert@xsharp.eu
Float, Real8, or Decimal?
Hello Chris, Robert,
Thanks for explanations.
Dick
Thanks for explanations.
Haha, that's quite remarkable. I had the same when I did the reverse many years ago.....Personally I got rid of many 5333s in VO by doing exactly that, replacing data types in intense calculations from FLOAT to REAL8.
Dick