Incorrect multiplication result

127 views
Skip to first unread message

Sainan

unread,
Jan 6, 2025, 7:39:14 AMJan 6
to lu...@googlegroups.com
Hi, I've been trying to implement LCG[1] in Lua, but I've encountered a strange issue:

print((-2740105712118473000) * 0x5851F42D4C957F2D)

This code prints '-6111441440935226376' even tho the expected result is '12335302632774325240'.

I'm not sure how exactly Lua comes to have the wrong result because under two's complement, the multiplication should be identical for signed and unsigned operands. I also can't find anything in lvm.c that would suggest special overflow handling.

[1] https://en.wikipedia.org/wiki/Linear_congruential_generator

-- Sainan

Xmilia Hermit

unread,
Jan 6, 2025, 7:47:41 AMJan 6
to lu...@googlegroups.com
Sainan:
> Hi, I've been trying to implement LCG[1] in Lua, but I've encountered a strange issue:
>
> print((-2740105712118473000) * 0x5851F42D4C957F2D)
>
> This code prints '-6111441440935226376' even tho the expected result is '12335302632774325240'.

I get the same result of -6111441440935226376 with my calculator and in
Java too. Are you sure you got the numbers right?

Regards,
Xmilia

Sainan

unread,
Jan 6, 2025, 7:51:31 AMJan 6
to lu...@googlegroups.com
Urg, I was just comparing it to C++, except now I can't replicate it anymore. Maybe I did get the numbers wrong. I'm still debugging; I'll see if I encounter this particular issue again.

-- Sainan

Christophe Delord

unread,
Jan 6, 2025, 7:52:54 AMJan 6
to 'Sainan' via lua-l
Le 06/01/2025 à 13:39, 'Sainan' via lua-l a écrit :
Hi, I've been trying to implement LCG[1] in Lua, but I've encountered a strange issue:

    print((-2740105712118473000) * 0x5851F42D4C957F2D)

This code prints '-6111441440935226376' even tho the expected result is '12335302632774325240'.

Both numbers have the same 64-bit representation (one is signed, the other one is unsigned).

Sainan

unread,
Jan 6, 2025, 7:54:10 AMJan 6
to lu...@googlegroups.com
> Both numbers have the same 64-bit representation (one is signed, the other one is unsigned).

Oooooooh. Now I feel stupid. Gonna be using hex from now on, I think.

-- Sainan

Philippe Verdy

unread,
Jan 7, 2025, 10:55:07 AMJan 7
to lu...@googlegroups.com
The first negative décimal number results in a 64-bit double with overflowing but with some precision loss, so the negative sign is preserved. The second hexadecimal number is a 64bit integer. The multiplication converts the second number to a 64-bit double, keeping its positive sign and the result is a negative 64-bit double.

--
You received this message because you are subscribed to the Google Groups "lua-l" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lua-l+un...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/lua-l/467bf1c1-1e32-4fc5-abcc-56ec1547346e%40cdelord.fr.

Philippe Verdy

unread,
Jan 7, 2025, 11:03:35 AMJan 7
to lu...@googlegroups.com
Also the two numbers are clearly different even as 64-bit integers (signed or not)
The first negative decimal would be
0xD9F9305F5E28DED8 as signed 64-bit

--
You received this message because you are subscribed to the Google Groups "lua-l" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lua-l+un...@googlegroups.com.

l...@cdelord.fr

unread,
Jan 7, 2025, 11:33:19 AMJan 7
to lu...@googlegroups.com, Philippe Verdy
Both values (modulo 2^64) have the same 64 bit encoding.


❯ cat foo.c                                                                      #include <stdio.h>
#include <stdint.h>

int main(void) {
  uint64_t x = 12335302632774325240LLU;
  int64_t y = -6111441440935226376;
  printf("x = 0x%016lx\n", x);
  printf("y = 0x%016lx\n", y);
}

anonymous in ~ via C v19.1.4-clang
❯ gcc foo.c

anonymous in ~ via C v19.1.4-clang
❯ ./a.out
x = 0xab2fcc63a77453f8
y = 0xab2fcc63a77453f8

Gé Weijers

unread,
Jan 8, 2025, 9:47:51 AMJan 8
to lu...@googlegroups.com
On Tue, Jan 7, 2025 at 7:55 AM Philippe Verdy <ver...@gmail.com> wrote:
The first negative décimal number results in a 64-bit double with overflowing but with some precision loss, so the negative sign is preserved. The second hexadecimal number is a 64bit integer. The multiplication converts the second number to a 64-bit double, keeping its positive sign and the result is a negative 64-bit double.


If you format it as unsigned number you get the result the original post was expecting:

Lua 5.4.7  Copyright (C) 1994-2024 Lua.org, PUC-Rio
> print(("%u"):format((-2740105712118473000) * 0x5851F42D4C957F2D))
12335302632774325240
> math.type(-2740105712118473000)
integer
> math.type((-2740105712118473000) * 0x5851F42D4C957F2D)
integer
>

Also, no conversion to double is taking place. Are you running an old version of Lua that does not use integer representation yet?


--

Reply all
Reply to author
Forward
0 new messages