Lcm (least common multiple) unexpected negative, overflow?

I’m quite new to SuperCollider and I wonder why lcm returns a negative number for positive operands

12128*2943*3544;
//-> 1940891392
[12128,2943,3544].reduce(\lcm);
//-> -1368001312

Is this due to an numeric overflow of integer? Can I workaround this? Is there a better way to calculate the lcm?

Thanks for you help.
Chris

Hi and welcome,

This is an erroneous result because you are silently exceeding the 32 bit integer limit – subtle! Compare the float result:

a = 12128.0 * 2943 * 3544;
a.dump;

   Float 126494942976.000000   A7000000 423D73AF
-> 126494942976

This number would need 37 bits:

log2(a)
-> 36.880288753667

You could take the factors method to show the prime factorization and calculate the lcm from them. Or you take lcmByFactors from the miSCellaneous_lib quark which does exactly that. From the example 4b in the help file “Sieves and Psieve patterns”:

// The result of an Integer multiplication is an Integer, 
// thus crossing the int32 limit is silent and can easily be overlooked

3768562 * 876876

-> 1731721688


3768562.0 * 876876

-> 3304561572312


// The methods lcmByFactors and lcmByGcd contain the relevant threshold checkes,
// they are much slower than 'lcm' but reliable also with large Integers.
// 'lcmByFactors' returns an array with lcm as first item, an array with prime factors
// of lcm as second item and an array of receiver's and all arguments' prime factors. 
// Alternatively the least common multiple can be calculated 
// via the greatest common divisor, this is done by method 'lcmByGcd'

lcmByFactors(248214, 1027542)
lcmByGcd(248214, 1027542)


// if calculation exceeds the int32 limit a warning is given, the result is a float

lcmByFactors(135630546, 429496729)
lcmByGcd(135630546, 429496729)


// also more args can be passed (all are integers < 2 * 31),
// as lcmByGcd uses gcd internally, this might fail with more than 2
// large numbers, whereas lcmByFactors still finds the result

lcmByGcd(135630546, 429496729, 610337457)
lcmByFactors(135630546, 429496729, 610337457)

/////////////////////////////////////////////

Applied to your numbers it returns:

[12128, 2943, 3544].lcmByFactors

WARNING: exceeding int32 bound, returning float
-> [ 15811867872, [ 2, 2, 2, 2, 2, 3, 3, 3, 109, 379, 443 ], [ [ 2, 2, 2, 2, 2, 379 ], [ [ 3, 3, 3, 109 ], [ 2, 2, 2, 443 ] ] ] ]

@dkmayer thanks a lot. based on lcmByFactors I managed to implement a harmonic dissonance metric for arbitrary chords based on Cubarsi, 2019, formular (39). I’d be glad for a review History for classes/Chord.sc - chris75vie/DissonanceLib · GitHub