[Scilab-users] lcm() output type: how to avoid overflowing and get an actual result?
Samuel Gougeon
sgougeon at free.fr
Wed Mar 15 18:09:25 CET 2017
Le 15/03/2017 à 17:04, Samuel Gougeon a écrit :
> Hello,
>
> Processing the bughttp://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?
Another solution could be to implement an /outputType/ option for lcm(),
in order to let the user choosing the expected behavior, with the
following possible values:
"asInput", "decimal", explicit inttype, "best", ...
But with which default value? :)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.scilab.org/pipermail/users/attachments/20170315/48070f91/attachment.htm>
More information about the users
mailing list