Is there a way to do signed 16 bit integer math?
6 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
Jeremy Shidner
le 7 Sep 2017
Commenté : Wil Koenen
le 6 Sep 2018
The following computation done in MATLAB:
a=int16(32558);
b=int16(-32333);
c=b-a;
Yields a c value of -32768.
In standard C programming, the same computation written as:
signed short a=32558,b=-32333,c;
c=b-a;
Yields a c value of 645.
How do I align MATLAB math operations with standard C integer math operations?
0 commentaires
Réponse acceptée
James Tursa
le 7 Sep 2017
Modifié(e) : James Tursa
le 7 Sep 2017
"... In standard C programming ..."
Well, sort of. Signed integer overflow behavior is not really defined in the C language. It is left up to the compiler to determine what happens for a particular implementation. Also there is the fact that binary operations in C (such as minus) with integers shorter than an int will first be converted to int to do the calculation (even if the shorter integer is unsigned). So your calculation above is actually done as follows assuming e.g. short is 16-bit and int is 32-bit:
signed short a=32558, b=-32333, c;
c = (signed short)( (int)b - (int)a );
So the subtraction is done with int's and there is no overflow for the result at the int level using the values you have above. The overflow actually occurs on the assignment, and that is where the particular compiler rules for this behavior come into play.
Now as it turns out, most platforms these days use 2's complement for integer representation and the C compilers choose to handle signed integer overflow by silently maintaining the same bit pattern of the operation result in a modulo sense, but this is not a requirement and it is not mandated that things work this way.
MATLAB truncates integer overflow operations, so yes there will be a mismatch. To get the same behavior at the MATLAB level, you would first need to convert all operands to single or double, do the operation, then modulo the result with an appropriate value depending on the bitsize of the intended target (int8 or int16 etc), and finally store that result in the integer variable. E.g.,
c = int16(mod(double(b)-double(a),32768));
2 commentaires
Wil Koenen
le 6 Sep 2018
The overflow/underflow emulation here is wrong. For example, if
a = -1;
b = intmax('int16');
then the operation should overflow and produce -32768 (or: intmin('int16')), but it doesn't:
c = int16(mod(double(b)-double(a), 32768))
intmin('int16')
The correct method is as follows. If 'M' is the number of bits, then we define:
R = 2^M; % full range
R_2 = R/2; % half range
Note that the following are all true
intmin('uintM') == 0
intmax('uintM') == R - 1
intmin('intM') == -R_2
intmax('intM') == R_2 - 1
Now, if 'd' is the result of the double operation, then for unsigned arithmetic we must round as follows:
uintM(mod(d, R))
and for signed arithmetic:
intM(mod(d + R_2, R) - R_2)
As an example, try:
M = 16; R = 2^M; R_2 = R/2;
% wrap functions
ru = @(d) uint16(mod(d, R))
ri = @(d) int16(mod(d + R_2, R) - R_2)
% uint16 ranges from 0 to 65535
% int16 ranges from -32768 to 32767
ru(double(intmax('uint16')) + (-3:3)) % overflow
ru(double(intmin('uint16')) + (-3:3)) % underflow
ri(double(intmax('int16')) + (-3:3)) % overflow
ri(double(intmin('int16')) + (-3:3)) % underflow
Plus de réponses (0)
Voir également
Catégories
En savoir plus sur Logical dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!