[Scilab-users] lcm() output type: how to avoid overflowing and get an actual result?
Tim Wescott
tim at wescottdesign.com
Wed Mar 15 18:57:59 CET 2017
So, a quick test gives me:
-->A = uint8([123 423]); A / lcm(A)
ans =
2 2
This looks pretty "least common multiple" to me. If I want a least
common multiple over decimal numbers or floats or bigger integers or
whatever, then it's my responsibility to tell the function that's what
I want by appropriately casting the type of the input.
A note in the help section about this (desirable, IMHO) behavior would
probably be a Good Idea though.
On Wed, 2017-03-15 at 17:04 +0100, Samuel Gougeon wrote:
> Hello,
>
> Processing the bug http://bugzilla.scilab.org/15017 for the lcm()
> function
> deserves an open discussion about the datatype of the result when the
> operand
> is a matrix of encoded integers.
> Presently, the result of lcm(A) has the type of A:
>
> --> r = lcm(int16([123 423])), typeof(r)
> r =
> 17343
> ans =
> int16
>
> --> r = lcm(uint8([123 423])), typeof(r)
> r =
> 61
> ans =
> uint8
>
> This behavior is questionable, in the way that the Least Common
> Multiple of some
> integers is always equal or most often greater than the maximum of
> the operand.
> Therefore, when the operand is a matrix of encoded integers, the LCM
> can easily
> (and most often) yield an overflow, and so yield a wrapped result,
> being most often
> unrelevant and misleading:
> Example:
> --> A = int8([2 3 5 7]);
> --> lcm(A)
> ans =
> -46 // 210 expected
> --> typeof(lcm(A))
> ans =
> int8
>
> So we see that even with few and small input values, as expected the
> result is already
> "corrupted".
>
> This bad effect does not happens with gcd() because its results is
> always
> smaller or equal to the maximum of the operand components.
>
> Octave behaves in the same bad way than Scilab, just saturating to
> the highest
> integer value instead of wrapping it, but in both cases the result is
> wrong:
>
> >> A = int8([2 3 5 7]);
> >> lcm(A(1), A(2), A(3), A(4))
> ans = 127
>
> So, the question is: Do we improve the situation, and if we do, in
> which way?
> Here are some suggestions:
>
> * The result is always promoted to the next class of inttype:
> int8 => int16, uint8 => uint16, int16 => int32, etc
> int64 and uint64 could be promoted into decimal numbers, but with a
> possible
> loss of accuracy (but beyond 2^63)
>
> * The result is always promoted to the most accurate (int64 or)
> uint64 class
>
> * The result is always promoted to the decimal (aka floating point)
> class
>
> My (slight) preference would be to cast the result always into the
> decimal class. Why?
> - the type of the result would be always the same: decimal
>
> - it would be OK and lossless for all int8, uint8, int16, and uint16
> operands,
> and for all int32, uint32, int64, uint64 smaller than 2^26
> OK, we could loose some low bits when processing some big 32 or 64
> bits integers,
> but at least we would have a result ; otherwise, casting to uint64
> could still
> lead to some overflow, so no actual result at all.
>
> - Usual +,-,*,/,^ operators between an int# or uint# and a decimal
> number forces
> the result to the encoded integer type. So this choice would let
> any further
> operations recasting the lcm() result into the original inttype
> (instead of
> promoting all further results in an unexpected way).
>
> What's your opinion? What would you prefer working with?
>
> Hope reading you soon
> Samuel
>
> _______________________________________________
> users mailing list
> users at lists.scilab.org
> http://lists.scilab.org/mailman/listinfo/users
--
Tim Wescott
www.wescottdesign.com
Control & Communications systems, circuit & software design.
Phone: 503.631.7815
Cell: 503.349.8432
More information about the users
mailing list