Hi Arne,
I'm waiting for the moment when I can replace all floats in amounts with decimals - I'm very tired about all the issues with floats.
For other things like seconds() or others I a float is enough.
Wolfgang
Float, Real8, or Decimal?
Float, Real8, or Decimal?
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
Float, Real8, or Decimal?
Hi Arne,
Indeed Seconds() returns a REAL8, that's because it is defined in XSharp.Core, which does not know about FLOATs, but can be easily moved to the other dlls and return a FLOAT instead. But it should not be really important, REAL8 and FLOAT are basically the same thing, FLOAT just has extra information about how to print the value (so about conversion to string), but that has nothing to do with calculations.
Val() returns a USUAL and USUALs can only hold INTs or FLOATs (And System.Decimal in X#), so it never returns a REAL8. But as I said this still should be no problem to use Val() together with either FLOATs or REAL8s.
Can you please post a sample code of something not behaving well? I suspect it is just a "showing on screen" issue, one of the REAL8/FLOAT/USUAL -> STRING functions not converting numbers to strings with the intended accuracy, or something along those lines.
Indeed Seconds() returns a REAL8, that's because it is defined in XSharp.Core, which does not know about FLOATs, but can be easily moved to the other dlls and return a FLOAT instead. But it should not be really important, REAL8 and FLOAT are basically the same thing, FLOAT just has extra information about how to print the value (so about conversion to string), but that has nothing to do with calculations.
Val() returns a USUAL and USUALs can only hold INTs or FLOATs (And System.Decimal in X#), so it never returns a REAL8. But as I said this still should be no problem to use Val() together with either FLOATs or REAL8s.
Can you please post a sample code of something not behaving well? I suspect it is just a "showing on screen" issue, one of the REAL8/FLOAT/USUAL -> STRING functions not converting numbers to strings with the intended accuracy, or something along those lines.
Chris Pyrgas
XSharp Development Team
chris(at)xsharp.eu
XSharp Development Team
chris(at)xsharp.eu
- lumberjack
- Posts: 727
- Joined: Fri Sep 25, 2015 3:11 pm
- Location: South Africa
Float, Real8, or Decimal?
Hi Arne,
This can easily be converted and obsoleting midnight rollover
Regards,
I think sometimes we need to also ask, is floating points still necessary, or can we rather convert to integer types?ArneOrtlinghaus wrote: Stay with floats or convert to another type, that's the question...
DOTNET allows us to completely move away from floating points in this scenario:I had now an issue using the function Seconds() together with float variables in x#.
Code: Select all
local fsecstart := Seconds() as float
local fdiff as float
... do something
fdiff := Seconds()-fsecstart
// in the following condition the difference of the new seconds()
// minus the previous seconds() call converted to float was unexpectedly smaller than 0
// The reason seem to be the mixing of float and real8
// In the VO-program this was treated correctly, but also in the X#-Program converting everything to real8
if fdiff < 0
fdiff += 86400 // for midnight change
endif
Code: Select all
var dstart := DateTime.Now
... do something
var diff := DateTime.Now:Ticks - dstart:Ticks // No worry about midnight
______________________
Johan Nel
Boshof, South Africa
Johan Nel
Boshof, South Africa
- ArneOrtlinghaus
- Posts: 412
- Joined: Tue Nov 10, 2015 7:48 am
- Location: Italy
Float, Real8, or Decimal?
Hi Chris,
it took a while to make a sample program that shows the behavior. Now I have succeeded. It shows it only sometimes. So there is a loop of 100000 to have some occurrences. When changing the variables to real8, the behavior did not occur until now.
I have attached the project. It is the function testseconds.
Arne
it took a while to make a sample program that shows the behavior. Now I have succeeded. It shows it only sometimes. So there is a loop of 100000 to have some occurrences. When changing the variables to real8, the behavior did not occur until now.
I have attached the project. It is the function testseconds.
Arne
- Attachments
-
- ConsoleApplication1.zip
- (622.81 KiB) Downloaded 59 times
-
- ConsoleApplication1.zip
- (622.81 KiB) Downloaded 53 times
- ArneOrtlinghaus
- Posts: 412
- Joined: Tue Nov 10, 2015 7:48 am
- Location: Italy
Float, Real8, or Decimal?
Hi Johann,
interesting, that your example should work. I can't believe:-) How could they have implemented it, that it works?
var dstart := DateTime.Now
... do something
var diff := DateTime.Now:Ticks - dstart:Ticks // No worry about midnight
interesting, that your example should work. I can't believe:-) How could they have implemented it, that it works?
var dstart := DateTime.Now
... do something
var diff := DateTime.Now:Ticks - dstart:Ticks // No worry about midnight
- lumberjack
- Posts: 727
- Joined: Fri Sep 25, 2015 3:11 pm
- Location: South Africa
Float, Real8, or Decimal?
Hi Arne,
I had in Vulcan days actually published on the GrafX NG a DateClass where I played and encapsulated most of the Clipper Date functions using the DateTime class, DoW, MoY, etc. Also added some additional ones, B/EoQ(uarter), B/EoT(erm), B/EoS(emester) and a "Financial" class where the methods/properties adhere to a Financial year start (the first month of the FY) property. Might need to dig it up and ask Robert to publish it in the downloads/contrib area.
But in essence, it provides us with an alternative Seconds() function that will only not work at the EoT, instead of End of Day. We hopefully created a bug that will only be discovered "After our Time"...
Well I have not tested it, but... MinValue is in DOTNET terms the "Beginning of Time" (BoT), 10000 Ticks make 0.001 seconds. MaxValue is "End of Time" (EoT), which implies we need to finish our software before that Dooms/rollover tick..ArneOrtlinghaus wrote: interesting, that your example should work. I can't believe:-) How could they have implemented it, that it works?Code: Select all
var dstart := DateTime.Now ... do something var diff := DateTime.Now:Ticks - dstart:Ticks // No worry about midnight
I had in Vulcan days actually published on the GrafX NG a DateClass where I played and encapsulated most of the Clipper Date functions using the DateTime class, DoW, MoY, etc. Also added some additional ones, B/EoQ(uarter), B/EoT(erm), B/EoS(emester) and a "Financial" class where the methods/properties adhere to a Financial year start (the first month of the FY) property. Might need to dig it up and ask Robert to publish it in the downloads/contrib area.
But in essence, it provides us with an alternative Seconds() function that will only not work at the EoT, instead of End of Day. We hopefully created a bug that will only be discovered "After our Time"...
______________________
Johan Nel
Boshof, South Africa
Johan Nel
Boshof, South Africa
-
- Posts: 248
- Joined: Fri Oct 14, 2016 7:09 am
Float, Real8, or Decimal?
I may be wrong but I think you don't need to reference the ticks anyway.... Just DateTime.Now-dstart is sufficient and will return a TimeSpan.
Nick
Nick
- lumberjack
- Posts: 727
- Joined: Fri Sep 25, 2015 3:11 pm
- Location: South Africa
Float, Real8, or Decimal?
Hi Nick,
Regards,
Yes you are correct, I just used Ticks for explanatory purposes since Ticks provide a "unique" representation of a DateTime object.NickFriend wrote:I may be wrong but I think you don't need to reference the ticks anyway.... Just DateTime.Now-dstart is sufficient and will return a TimeSpan.
Regards,
______________________
Johan Nel
Boshof, South Africa
Johan Nel
Boshof, South Africa
Float, Real8, or Decimal?
Hi Arne,
Thanks, I see the problem and I found what's causing it, it's a bug in the "<" operator code for FLOATs, it does not treat the SetFloatDelta() correctly (if you set SetFloatDelta(0) then your code works fine). Will send you a fix for that.
Chris
Thanks, I see the problem and I found what's causing it, it's a bug in the "<" operator code for FLOATs, it does not treat the SetFloatDelta() correctly (if you set SetFloatDelta(0) then your code works fine). Will send you a fix for that.
Chris
Chris Pyrgas
XSharp Development Team
chris(at)xsharp.eu
XSharp Development Team
chris(at)xsharp.eu
- ArneOrtlinghaus
- Posts: 412
- Joined: Tue Nov 10, 2015 7:48 am
- Location: Italy
Float, Real8, or Decimal?
Hi Chris,
thank you for verifying and resolving this. I didn't even know that there is this setfloatdelta after 20 years of VO programming....
Looking into ILSpy for me the influencing code seems to be in the class sharp.__Float in the xsharp.rt and there in the operator method
public static Logicoperator <(lhs as __Float , rhs as __Float )
where the floatdelta may influence the comparison result.
Similarly there are many other operators overwritten, that may influence behavior of float compared to real8.
The usual type seems to be the __Usual in the Xsharp.RT.
There is a similar operator
public static Logicoperator <(lhs as __Usual , rhs as __Usual )
When looking there what is inserted there it seems that always two real8 variables are compared.
I find this ok, because it seems that the usual type is performance optimized as much as possible, with the effect that it uses more real8 behavior than VO that seems to use the float variable behavior in usuals.
My conclusion is again for moving code from VO to X#:
Try to convert every float to real8, also if you use many usuals.
- The advantage is having always a clear floating behavior similar to other languages
- The performance and memory behavior is better.
- Compared to Float in VO there may be about two decimals less of accuracy, but the accuracy in X# should be equal for float and real8, because float is based on real8 (double).
- Limiting everything to exactly one floating type avoids strange behaviors difficult to understand.
- Comparison of equal between two floating numbers should work only if the numbers are really 0, same as for most other computer languages, otherwise always the absolute difference must be lower a certain limit.
- The biggest differences may appear using the function Str without specifying the number of decimals and the NTrim function. Obviously when using real8 there will be more decimals displayed. A possibility to use a substitution similar to the attached function NTrimSafe, that automatically removes 0 decimals. At least when assigning integer values to real8 this should display data without shocking users. Better is to use str always with a correct specification of the decimals.
Arne
thank you for verifying and resolving this. I didn't even know that there is this setfloatdelta after 20 years of VO programming....
Looking into ILSpy for me the influencing code seems to be in the class sharp.__Float in the xsharp.rt and there in the operator method
public static Logicoperator <(lhs as __Float , rhs as __Float )
where the floatdelta may influence the comparison result.
Similarly there are many other operators overwritten, that may influence behavior of float compared to real8.
The usual type seems to be the __Usual in the Xsharp.RT.
There is a similar operator
public static Logicoperator <(lhs as __Usual , rhs as __Usual )
When looking there what is inserted there it seems that always two real8 variables are compared.
I find this ok, because it seems that the usual type is performance optimized as much as possible, with the effect that it uses more real8 behavior than VO that seems to use the float variable behavior in usuals.
My conclusion is again for moving code from VO to X#:
Try to convert every float to real8, also if you use many usuals.
- The advantage is having always a clear floating behavior similar to other languages
- The performance and memory behavior is better.
- Compared to Float in VO there may be about two decimals less of accuracy, but the accuracy in X# should be equal for float and real8, because float is based on real8 (double).
- Limiting everything to exactly one floating type avoids strange behaviors difficult to understand.
- Comparison of equal between two floating numbers should work only if the numbers are really 0, same as for most other computer languages, otherwise always the absolute difference must be lower a certain limit.
- The biggest differences may appear using the function Str without specifying the number of decimals and the NTrim function. Obviously when using real8 there will be more decimals displayed. A possibility to use a substitution similar to the attached function NTrimSafe, that automatically removes 0 decimals. At least when assigning integer values to real8 this should display data without shocking users. Better is to use str always with a correct specification of the decimals.
Arne
- Attachments
-
- ntrimremovedecimals.txt
- (3.03 KiB) Downloaded 63 times