Welcome, Guest
Username: Password: Remember me
Visual Objects

Please use this forum to post questions about Visual Objects and Vulcan.NET

TOPIC:

Float, Real8, or Decimal? 18 Feb 2019 14:01 #7375

  • wriedmann
  • wriedmann's Avatar


  • Posts: 3242
  • 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
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 18 Feb 2019 15:05 #7376

    • Chris
    • Chris's Avatar


  • Posts: 3736
  • 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.
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 19 Feb 2019 06:02 #7380

    • lumberjack
    • lumberjack's Avatar


  • Posts: 720
  • Hi Arne,

    ArneOrtlinghaus wrote: Stay with floats or convert to another type, that's the question...

    I think sometimes we need to also ask, is floating points still necessary, or can we rather convert to integer types?

    I had now an issue using the function Seconds() together with float variables in x#.

    DOTNET allows us to completely move away from floating points in this scenario:
    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
    This can easily be converted and obsoleting midnight rollover
    var dstart := DateTime.Now
    ... do something
    var diff := DateTime.Now:Ticks - dstart:Ticks // No worry about midnight
    Regards,
    ______________________
    Johan Nel
    Boshof, South Africa

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 20 Feb 2019 08:28 #7389

    • ArneOrtlinghaus
    • ArneOrtlinghaus's Avatar
    • Topic Author


  • Posts: 337
  • 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

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 20 Feb 2019 08:32 #7390

    • ArneOrtlinghaus
    • ArneOrtlinghaus's Avatar
    • Topic Author


  • Posts: 337
  • 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

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 20 Feb 2019 09:18 #7395

    • lumberjack
    • lumberjack's Avatar


  • Posts: 720
  • Hi Arne,

    ArneOrtlinghaus wrote: 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

    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.. :evil:

    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

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 20 Feb 2019 10:05 #7396

    • NickFriend
    • NickFriend's Avatar


  • Posts: 238
  • 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

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 20 Feb 2019 10:42 #7397

    • lumberjack
    • lumberjack's Avatar


  • Posts: 720
  • Hi Nick,

    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.

    Yes you are correct, I just used Ticks for explanatory purposes since Ticks provide a "unique" representation of a DateTime object.
    Regards,
    ______________________
    Johan Nel
    Boshof, South Africa

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 20 Feb 2019 18:43 #7400

    • Chris
    • Chris's Avatar


  • Posts: 3736
  • 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
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 21 Feb 2019 10:27 #7404

    • ArneOrtlinghaus
    • ArneOrtlinghaus's Avatar
    • Topic Author


  • Posts: 337
  • 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

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 21 Feb 2019 10:48 #7405

    • ArneOrtlinghaus
    • ArneOrtlinghaus's Avatar
    • Topic Author


  • Posts: 337
  • I have now verified what is the setfloatdelta in our programs without having specified it.
    It gives:
    0,0000000000001

    Now I can again think about what I have written some minutes before and the consequences...

    ... Fortunately in our programs we should have already made more stable most of the floating comparisons using the following operations.
    function NumEQU (nWert1 as real8,nWert2 as real8) as logic strict
    //p Prüfung, ob zwei Werte bis auf Rundungen gleich sind
    //g Math
    //g General
    if Abs(nWert1) < 1.E3
    return (abs(nWert2-nWert1) < (1.E-11))
    elseif Abs(nWert1) < 1.E6
    return (abs(nWert2-nWert1) < (1.E-8))
    elseif Abs(nWert1) < 1.E9
    return (abs(nWert2-nWert1) < (1.E-5))
    else
    return (abs(nWert2-nWert1) < (1.E-3))
    endif

    function NumGEQ (nWert1 as real8,nWert2 as real8) as logic strict
    //p Prüfung, ob ein Wert bis auf Rundungen größer gleich als ein anderer ist
    //g Math
    //g General
    return NumEQU (nWert1,nWert2) .or. nWert1 > nWert2

    function NumGTR (nWert1 as real8,nWert2 as real8) as logic strict
    //p Prüfung, ob ein Wert bis auf Rundungen größer als ein anderer ist
    //g Math
    //g General
    return !NumEQU (nWert1,nWert2) .and. nWert1 > nWert2

    function NumLEQ (nWert1 as real8,nWert2 as real8) as logic strict
    //p Prüfung, ob ein Wert bis auf Rundungen kleiner gleich ein anderer ist
    //g Math
    //g General
    return NumEQU (nWert1,nWert2) .or. nWert1 < nWert2

    function NumLSS (nWert1 as real8,nWert2 as real8) as logic strict
    //p Prüfung, ob ein Wert bis auf Rundungen kleiner als ein anderer ist
    //g Math
    //g General
    return !NumEQU (nWert1,nWert2) .and. nWert1 < nWert2

    function NumNEQ (nWert1 as real8,nWert2 as real8) as logic strict
    //p Prüfung, ob zwei Werte bis auf Rundungen ungleich sind
    //g Math
    //g General
    return !NumEQU (nWert1,nWert2)

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 21 Feb 2019 14:58 #7407

    • Chris
    • Chris's Avatar


  • Posts: 3736
  • Hi Arne,

    The problem is the precision of the real8 data type with decimal numbers, if you try this in any language:

    LOCAL r1,r2 AS REAL8
    r1 := 0.1
    r2 := 0.3
    r1 := r1 * 3.0
    ? r1 == r2 // FALSE!

    this will return FALSE in all languages, including VO, X#, c# etc, because in binary format the value 0.1 cannot be exactly represented, so when doing math on it, you just go further away from the actual value.

    VO attempted to overcome this inherent limitation of floating types by introducing SetFloatDelta(), which does work, but up to a point only, before needing to specify a larger value for SetFloatDelta(). In .Net this was fixed by introducing the System.Decimal data type, which can accurately represent decimal numbers, so you do not have to worry at all about the above anymore. Only problem is that it is slower than REAL8, which might become a problem if your calculations are extremely extensive.

    Chris
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 22 Feb 2019 11:21 #7416

    • Otto
    • Otto's Avatar


  • Posts: 174
  • ArneOrtlinghaus wrote: Hi Chris,
    I didn't even know that there is this setfloatdelta after 20 years of VO programming....

    same here... oh brother... would have saved us a lot of trouble.

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 22 Feb 2019 11:36 #7417

    • wriedmann
    • wriedmann's Avatar


  • Posts: 3242
  • Hi Arne, hi Otto,

    using SetFloatDelta() is a relatively easy possibility to keep the problems of the floating point mess as low as possible.

    I'm very happy that such a thing like the Decimal datatype exists in .NET!

    Wolfgang
    P.S. my first programming experience was Cobol, and there is absolutely no problem with decimal variables if you don't use binary datatypes.
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 22 Feb 2019 11:40 #7418

    • lumberjack
    • lumberjack's Avatar


  • Posts: 720
  • Otto wrote:

    ArneOrtlinghaus wrote: I didn't even know that there is this setfloatdelta after 20 years of VO programming....

    same here... oh brother... would have saved us a lot of trouble.

    It makes me think back to this in the c.l.c.vo NG...
    Willie Moore 	
    8/31/07
    Hey,
    Here is a small tip and function in you ever run into any VB code that you need to translate to VO. in VB, int returns the integer part of the number ignoring the fractional part. But, if the number is negative, it take the abs of the fraction and if it is greater than 0, it returns the next negative number less than the passed number. So, if the number is int(-8.01) -n VB returns -9. (http://msdn2.microsoft.com/en-us/library/xh29swte(VS.71).aspx)
    If you have to convert VO code from VB, here is a function to handle it.
    Regards,
    Willie
    
    FUNCTION vbInt(nVar AS FLOAT) AS LONG PASCAL
       LOCAL nResult AS LONG
       LOCAL fFrac   AS FLOAT
       IF nVar >= 0
           nResult := INT(nVar)
       ELSE        
          fFrac := Frac(nVar)
          IF Abs(fFrac) > 0    
              nResult := INT(nVar) - 1
          ELSE
             nResult := INT(nVar)
         ENDIF
       ENDIF
       RETURN nResult
    Johan Nel
    8/31/07
    Hi Willie,
    Yes you right, VB and VO handle negative integers differently.
    You could also just use:
    FUNCTION vbInt(nVar)
      RETURN Floor(nVar)
    Willie Moore 	
    8/31/07
    Johan,
    Thanks. Dont think I have ever used floor. Makes the function ever more simple.
    Regards,
    Willie
    ______________________
    Johan Nel
    Boshof, South Africa

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 01 Dec 2020 23:06 #16834

    • Otto
    • Otto's Avatar


  • Posts: 174
  • Seems like SetFloatDelta doesn't work for Real8 in XSharp (VO).
    In VO it works for both Real8 the same way as for Float. :(

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 01 Dec 2020 23:12 #16835

    • robert
    • robert's Avatar


  • Posts: 3269
  • Otto,
    Thanks for the report.
    To make this work we will have to change the compiler to generate different code for Real8 comparisons, a bit like we are doing now for string comparisons (/vo13) and we will have to add comparison routines to the runtime.
    This is not very difficult but will take some time. Most likely we would add a new compiler option (vo17) for this.
    How important is this for you ?

    Robert
    XSharp Development Team
    The Netherlands

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 01 Dec 2020 23:13 #16836

    • Chris
    • Chris's Avatar


  • Posts: 3736
  • Hi Otto,

    Are you sure? I just tried this in VO and it returns FALSE for REAL8 and TRUE (as expected) for FLOAT:
    LOCAL r1,r2 AS REAL8
    LOCAL f1,f2 AS FLOAT
    SetFloatDelta(0.1)
    r1 := 0.01
    r2 := 0.02
    f1 := r1
    f2 := r2
    ? r1 == r2 // FALSE
    ? f1 == f2 // TRUE
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 01 Dec 2020 23:18 #16837

    • Otto
    • Otto's Avatar


  • Posts: 174
  • I've included the VO version.
    But I compare the Real8 with a literal 0.0
    Could it be that the 0.0 is seen as a float and that therefore the left hand side (real8) is converted into a float as wel?
    Attachments:

    Please Log in or Create an account to join the conversation.

    Float, Real8, or Decimal? 01 Dec 2020 23:21 #16838

    • Otto
    • Otto's Avatar


  • Posts: 174
  • About the importance:
    I'm looking for solutions for a lot of comparisons in my code between literal zero's and real8's.

    If I can figure a structural solution for this in another way that could be ok. I am aware of the trouble in general with floating point comparison...

    I'll come back on this tomorrow.

    Please Log in or Create an account to join the conversation.