Is ACF correct here? <https://trycf.com/gist/2dd7f...
# cfml-general
a
Yay for ChatGPT:
why might converting decimal -1234 to hex result in 0xfffffb2e rather than -0x4D2
When converting decimal -1234 to a 32-bit two's complement representation in hexadecimal, the correct result is -0x4D2. However, if you try to convert the decimal number to an unsigned 32-bit representation in hexadecimal, you may get 0xfffffb2e as the result.
This happens because when a decimal number is converted to hexadecimal, it is first converted to its binary representation. In the case of -1234, the binary representation in 32-bit two's complement form is 0b11111111111111111111100110101110.
If you interpret this binary number as an unsigned integer, you get 4294966062 (0xfffffb2e in hexadecimal). However, if you interpret it as a 32-bit two's complement signed integer, you get -1234 (which is represented as 0xfffffb2e in hexadecimal).
Therefore, it is important to specify whether you want to convert the decimal number to an unsigned or a signed hexadecimal representation, depending on the context of your problem.
That explains the result. Still thinking / researching as to whether I reckon that's what CF ought to be doing.
👍 1
z
one question, which comes to mind, does it round trip backwards
a
NB: it's been behaving that way since at least CF5.
https://trycf.com/gist/b9e3f5d1cb56467218aa2518357e6e33/lucee5?theme=monokai
Copy code
// cf / lucee
writeDump(formatBaseN(-1234,16)); // fffffb2e / -4d2
writeDump(formatBaseN(1234,16)); // 4d2 


writeDump(inputBaseN("fffffb2e", 16)); // 4294966062
writeDump(inputBaseN("-4d2", 16)); // -1234
Re round trip... it would seem reasonable to me that
formatBaseN
and
inputBaseN
follow the same rules re signed/unsigned ints
z
I just quickly cross ref-ed those two functions https://github.com/lucee/lucee-docs/pull/1369
a
PHP: https://onlinephp.io/c/83cd3d
Copy code
echo dechex(-1234); // fffffffffffffb2e
echo PHP_EOL;
echo dechex(1234); // 4d2
JS:
Copy code
(-1234).toString(16)
'-4d2'
(1234).toString(16)
'4d2'
Ruby:
Copy code
irb(main):001:0> -1234.to_s(16)
=> "-4d2"
Python:
Copy code
>>> print(hex(-1234))
-0x4d2
Groovy:
Copy code
groovy> Integer.toHexString(-1234) 
 
Result: fffffb2e
Java (via CFML...): (https://trycf.com/gist/909a4e1cbc53f26b32b6d5de30c3d72a/lucee5?theme=monokai)
Copy code
Long = createObject("java", "java.lang.Long")
l = createObject("java", "java.lang.Long").init(-1234)
n = -1234

writeDump([
    l = [
        type = l.getClass().getName(), // java.lang.Long
        hex = Long.toHexString(l) // fffffffffffffb2e
    ],
    n = [
        type = n.getClass().getName(), // 	java.lang.Double
        hex = Long.toHexString(n) // fffffffffffffb2e
    ]
])
So. I'd say there's basis for Lucee doing the way that it is, but there is also basis for the way CF does it, and it's always done it that way, so... it's right. I think that raw Java is the same also kinda provides the important precedent here.
z
great analysis, wanna drop that all into the ticket as a comment? https://luceeserver.atlassian.net/browse/LDEV-3776
a
Clojure is interesting though:
Copy code
user=> (Integer/toString -1234 16)
"-4d2"
Given it's a JVM language 'n' all. Indicates perhaps that my Java code is not the final word on how it works in Java. There's no doubt some (un)signed idiosyncracy that we ought to be considering.
I'd try to rope @seancorfield into this, as he's the brains of the outfit around here 😉
And yeah, will add all that bumpf onto the ticket.
z
thanks mate
a
I think there's def a Q for @Mark Takata (Adobe) in here too, as to whether the round trip via
inputBaseN
is working predictably / by design on CF.
z
Lucee is just doing
return Long.toString(Caster.toLongValue(number), (int) radix);
https://github.com/lucee/Lucee/blob/6.0/core/src/main/java/lucee/runtime/functions/displayFormatting/FormatBaseN.java#L33
a
^^ all that added to the ticket. I'm going back to shooting supermutants now, and wondering why my espresso doesn't see to have worked today.
Cheers for raising it though. For some reason I like checking how other languages do stuff.
m
This is a super awesome thread!
😜 1
🎉 1
s
Sorry, slow to respond to this. @Adam Cameron What you tried in Clojure is not quite what you tried in Java:
Copy code
build=> (Integer/toString -1234 16)
"-4d2"
build=> (Integer/toHexString -1234)
"fffffb2e"
1
And we can try that in Java to confirm:
Copy code
> jshell
May 08, 2023 3:57:07 PM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
|  Welcome to JShell -- Version 17.0.6
|  For an introduction type: /help intro

jshell> Integer.toString(-1234, 16);
$1 ==> "-4d2"

jshell> Integer.toHexString(-1234);
$2 ==> "fffffb2e"

jshell>
a
haha, sorry yeah. I just googled something like "clojure convert decimal to hex" and copy and pasted the first result I found.