Jump to content

Recommended Posts

  • Moderators
Posted

Ascer,

Not an AutoIt problem, but one that affects all computers that do not have a specialist maths app/CPU. This has been discussed many, many times - search the forum for "floating point arithmetic".

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

  • Moderators
Posted (edited)

Ascer,

I agree, but it is beyond AutoIt to do anything about it. Did you read anything about floating point arithmetic? it is a product of the way all computers store real numbers (i.e. non-integers) and, as I mentioned above, requires a special maths program or CPU do deal with it correctly.

In your case, just convert everything to integers:

$a = 3.99

$a = $a * 100
ConsoleWrite(VarGetType($a) & ": " & $a & @CRLF)

$a -= 300
ConsoleWrite(VarGetType($a) & ": " & $a & @CRLF)

$a -= 99
ConsoleWrite(VarGetType($a) & ": " & $a & @CRLF)

$a = $a/100
ConsoleWrite(VarGetType($a) & ": " & $a & @CRLF)

M23

Edited by Melba23
Added link

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Posted

One way of dealing with this issue is to round the final result or before doing any comparisons to a sensible number of decimal places.

 

$a = 3.99 - 3
ConsoleWrite(VarGetType($a) & ": " & $a & @CRLF)

$a *= 100
ConsoleWrite(VarGetType($a) & ": " & $a & @CRLF)

$a -= 99
ConsoleWrite(VarGetType($a) & ": " & $a & @CRLF)
ConsoleWrite(VarGetType($a) & ": " & Round($a,12) & @CRLF)

If $a = 0 Then
    ConsoleWrite(VarGetType($a) & ": $a = zero is True" & @CRLF)
Else
    ConsoleWrite(VarGetType($a) & ": $a = zero is False" & @CRLF)
EndIf

If Round($a,12) = 0 Then
    ConsoleWrite(VarGetType($a) & ": $a = zero is True" & @CRLF)
Else
    ConsoleWrite(VarGetType($a) & ": $a = zero is False" & @CRLF)
EndIf

 

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to build bigger and better idiots. So far, the universe is winning."- Rick Cook

Posted

It's not an AutoIt problem, but we still can do something about it by using variants of type decimal:

#include "Variant.au3"

Opt( "MustDeclareVars", 1 )

Example1()
Example2()

Func Example1()
  ConsoleWrite( "Example1" & @CRLF )

  Local $a = 3.99 - 3
  ConsoleWrite(VarGetType($a) & ": " & $a & @CRLF)

  $a *= 100
  ConsoleWrite(VarGetType($a) & ": " & $a & @CRLF)

  $a -= 99
  ConsoleWrite(VarGetType($a) & ": " & $a & @CRLF)
EndFunc

Func Example2()
  ConsoleWrite( @CRLF & "Example2" & @CRLF )

  Local $a = "3.99", $b = "3", $c = "100", $d = "99"
  ; The strings ensures that the numbers are not converted to floats

  Local $ta = StrToDec( $a ), $pa = DllStructGetPtr( $ta )
  Local $tb = StrToDec( $b ), $pb = DllStructGetPtr( $tb )
  Local $tc = StrToDec( $c ), $pc = DllStructGetPtr( $tc )
  Local $td = StrToDec( $d ), $pd = DllStructGetPtr( $td )

  VarDecSub( $pa, $pb, $pa ) ; $a = $a - $b = 3.99 -   3
  $a = DecToStr( $pa )
  ConsoleWrite( $a & @CRLF )
  VarDecMul( $pa, $pc, $pa ) ; $a = $a * $c =  $a  * 100
  $a = DecToStr( $pa )
  ConsoleWrite( $a & @CRLF )
  VarDecSub( $pa, $pd, $pa ) ; $a = $a - $d =  $a  -  99
  $a = DecToStr( $pa )
  ConsoleWrite( $a & @CRLF )
EndFunc

Func StrToDec( $str )
  Local $tStr = DllStructCreate( $tagVARIANT )
  Local $pStr = DllStructGetPtr( $tStr )
  $tStr.vt   = $VT_BSTR
  $tStr.data = SysAllocString( $str )
  VariantChangeType( $pStr, $pStr, 0, $VT_DECIMAL )
  Local $tDec = DllStructCreate( $tagDEC, $pStr )
  Local $l = StringInStr( $str, "." )
  $tDec.scale = $l ? StringLen( $str ) - $l : 0
  Return $tStr
EndFunc

Func VarDecAdd( $pDecLeft, $pDecRight, $pDecResult )
  Local $aRet = DllCall( "OleAut32.dll", "long", "VarDecAdd", "ptr", $pDecLeft, "ptr", $pDecRight, "ptr", $pDecResult )
  If @error Then Return SetError(1,0,1)
  Return $aRet[0]
EndFunc

Func VarDecDiv( $pDecLeft, $pDecRight, $pDecResult )
  Local $aRet = DllCall( "OleAut32.dll", "long", "VarDecDiv", "ptr", $pDecLeft, "ptr", $pDecRight, "ptr", $pDecResult )
  If @error Then Return SetError(1,0,1)
  Return $aRet[0]
EndFunc

Func VarDecMul( $pDecLeft, $pDecRight, $pDecResult )
  Local $aRet = DllCall( "OleAut32.dll", "long", "VarDecMul", "ptr", $pDecLeft, "ptr", $pDecRight, "ptr", $pDecResult )
  If @error Then Return SetError(1,0,1)
  Return $aRet[0]
EndFunc

Func VarDecSub( $pDecLeft, $pDecRight, $pDecResult )
  Local $aRet = DllCall( "OleAut32.dll", "long", "VarDecSub", "ptr", $pDecLeft, "ptr", $pDecRight, "ptr", $pDecResult )
  If @error Then Return SetError(1,0,1)
  Return $aRet[0]
EndFunc

Func DecToStr( $pDec )
  Local $tStr = DllStructCreate( $tagVARIANT )
  VariantChangeType( DllStructGetPtr( $tStr ), $pDec, 0, $VT_BSTR )
  Return SysReadString( $tStr.data )
EndFunc

You can get Variant.au3 in this post.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...