compare long numbers/strings

Report problems with documented functionality
pekoe
Posts: 6
Joined: 25 Mar 2016, 11:42

compare long numbers/strings

Post by pekoe » 28 Jun 2022, 05:13

; All 6 tests should return 0 ("false").
; With AutoHotkey v1.0 (without test 3 and 4, because format() doesn't exist in AutoHotkey v1.0) all 4 tests return 0.
; With the current version test 1, 3, 5 return 1.

Code: Select all

var1 := "11111111111111111110"
var2 := "11111111111111111111"
test1 := (var1 = var2)
test2 := (var1 . "" = var2 . "")
test3 := (format("{:s}", var1) = format("{:s}", var2))
test4 := (format("{:s}", var1) . "" = format("{:s}", var2) . "")
test5 := (11111111111111111110 = 11111111111111111111)
test6 := ("11111111111111111110" = "11111111111111111111")
msgbox % test1 test2 test3 test4 test5 test6
return
[Mod edit: [code][/code] tags added.]

gregster
Posts: 8921
Joined: 30 Sep 2013, 06:48

Re: compare long numbers/strings

Post by gregster » 28 Jun 2022, 09:42

It believe this is caused by the way AHK (the one of the last 10 years or so?) handles variable types, and how it automatically converts between types in certain situations when variables are read.

When used as numbers, you have to respect the variable ranges (which shouldn't surprise):
https://www.autohotkey.com/docs/Variables.htm#cap wrote:For integers, 64-bit signed values are supported, which range from -9223372036854775808 (-0x8000000000000000) to 9223372036854775807 (0x7FFFFFFFFFFFFFFF). Any integer constants or numeric strings outside this range are not supported and might yield inconsistent results when used as numbers. By contrast, arithmetic operations on integers wrap around upon overflow (e.g. 0x7FFFFFFFFFFFFFFF + 1 = -0x8000000000000000).
Your integers are larger, but you expect that they should still be seen as strings.
(btw, Avi has created a "scientifical math" library to calculate with bigger numbers: https://github.com/aviaryan/autohotkey-scripts/blob/master/Functions/Maths.ahk)

Well, AHK's variable caching might do smth else than you are expecting, for performance reasons. It might interpret a numeric string as a number. Concatenating it with "" can counter that behaviour:
https://www.autohotkey.com/docs/Concepts.htm#caching wrote: Although a variable is typically thought of as holding a single value, and that value having a distinct type (string, number or object), AutoHotkey automatically converts between numbers and strings in cases like myString + 1 and MsgBox %myNumber%. As these conversions can happen very frequently, whenever a variable is converted, the result is cached in the variable.

In effect, a variable can contain both a string and a number simultaneously. Usually this just improves the script's performance with no down-sides, but if a variable contains both a number and a string, is it number, or is it a string? This ambiguity causes unexpected behavior in at least two cases:[...]
AHK v2.beta on the other hand:
https://lexikos.github.io/v2/docs/Concepts.htm#caching wrote:Currently, AutoHotkey v2 caches a pure number only when assigning a pure number to a variable, not when reading it. This preserves the ability to differentiate between strings and pure numbers (such as with the Type function, or when passing values to COM objects).
I wouldn't expect a change in v1.1, as it could cause problems with backwards compatibility.
No idea what AHK 1.0 did - but when was the last version released? 11 years ago? Edit: lexikos said: "Prior to v1.0.48, even numbers assigned to variables were only stored as strings."

lexikos
Posts: 9560
Joined: 30 Sep 2013, 04:07
Contact:

Re: compare long numbers/strings

Post by lexikos » 29 Jun 2022, 03:25

Code: Select all

var1 := "11111111111111111110"
var2 := "11111111111111111111"
test1 := (var1 = var2)
When run on v1.0.48.05, this code does not compare "11111111111111111110" to "11111111111111111111". What it actually does is convert each string to a 64-bit number, and then compare the two numbers. Since these numbers are outside the supported range, the behaviour is effectively undefined. On the compiler used for the official v1.0.48.05 files, the out-of-range result of conversion for the two strings is different, so the comparison appears to perform correctly. Try this instead, and you will see what it is actually comparing:

Code: Select all

var1 := "11111111111111111110"
var2 := "11111111111111111111"
MsgBox % var1+0 "`n" var2+0
If you take the v1.0.48.05 source code and compile it, without changes (aside from the necessary project settings to make it work), using Visual C++ 2019 (or most likely anything newer than 2003), both numbers produce 9223372036854775807. Compare:
For _atoi64 in Visual C++ 2019, Microsoft wrote:In the case of overflow with large positive integral values, _atoi64 returns I64_MAX and I64_MIN in the case of overflow with large negative integral values.
For _atoi64 in Visual C++ 2003, Microsoft wrote:The return value is undefined in case of overflow.
VC++2003 will produce an incorrect result in this case, while VC++2019 will happen to produce the correct result (but how it arrives at that result is still no good):

Code: Select all

var1 := "11111111111111111110"
var2 := "11111111111111111111"
MsgBox % var1 = -7335632962598440506
MsgBox % var2 = -7335632962598440506

It believe this is caused by the way AHK (the one of the last 10 years or so?) handles variable types,
Which version of the last 10 years or so? AutoHotkey v2.0-a001 fixed some of these issues. That was in 2011.

Post Reply

Return to “Bug Reports”