I am converting a matlab code to Python. In matlab there is a line which converting the complex number to the int16:
real = int16(real(-3.406578165491512e+04 + 9.054663292273188e+03i));
imag= int16(imag(-3.406578165491512e+04 + 9.054663292273188e+03i));
real= -32768
imag=9055
In python I have tried this:
real = np.int16(round(np.real(-3.406578165491512e+04 + 9.054663292273188e+03j)))
imag = np.int16(round(np.imag(-3.406578165491512e+04 + 9.054663292273188e+03j)))
real= 31470
imag=9055
The results are different (I have had many other values such as (1.815808483565253e+04 + 3.533772674703890e+04j) with different answer!) would you please help me to get the same answer?
The primary advantage of using array scalars is that they preserve the array type (Python may not have a matching scalar type available, e.g. int16 ).
int16. Integer (-32768 to 32767)
Int32: This Struct is used to represents 32-bit signed integer. The Int32 can store both types of values including negative and positive between the ranges of -2147483648 to +2147483647.
int8, int16, int32, int64 (MATLAB Functions) MATLAB Function Reference int8, int16, int32, int64 Convert to signed integer Syntax
int8, int16, int32, int64 (MATLAB Functions) MATLAB Function Reference int8, int16, int32, int64 Convert to signed integer Syntax I = int8(X) I = int16(X) I = int32(X) I = int64(X)
Int16: This Struct is used to represents 16-bit signed integer. The Int16 can store both types of values including negative and positive between the ranges of -32768 to +32767. UInt16: This Struct is used to represents 16-bit unsigned integer.
The difference in results obtained when casting to INT8, INT16 or INT32 in MATLAB and Simulink is an expected behavior. Rounding is very interesting when it comes to tie values such as -0.5, 0.5, 1.5 etc. 1. Nearest rounding with ties rounded away from zero
The MATLAB output has saturated at intmin('int16') = -32768
(docs), i.e. the most negative value it can represent as an int16
variable.
Python has the same range for int16
(docs), but instead of saturating at the most negative value it has experienced underflow, wrapping around to the top of the range
k = round(-3.406578165491512e+04) = -34066
k = k + (32768*2) = 31470
You could get around this by enforcing whichever of these is your preferred behaviour when the inputs are still floating point values, and then when the input is within the range -32768 to 32767
you can cast it to int16
.
Wolfie gets at the difference, this is about how to solve it. If you're OK with clipping, then you can use iinfo to get the min and max values of an integer type (or hard-code it, if you know you won't be changing it from int16 ever) and then use clip to constrain the float to be within those bounds before casting it.
n = -3.406578165491512e+04
ii = np.iinfo(np.int16)
print(f"min = {ii.min}") # min = -32768
print(f"max = {ii.max}") # max = 32767
np.int16(np.clip(n, ii.min, ii.max))
# -32768
IMPORTANT NOTE: This is only reliable if the size if your float is larger than the size of the int, because it relies upon being able to represent ii.max
exactly as a float. See here for a discussion of when this is not true.
Here's an example of that failing
n = np.float64(1e100)
ii = np.iinfo(np.int64)
print(f"max: {ii.max}") # max = 9223372036854775807
clipped = np.clip(n, ii.min, ii.max)
print(f"clipped to: {int(clipped)}") # clipped to: 9223372036854775808
print(f"as int: {np.int64(clipped)}") # as int: -9223372036854775808
(This happens because ii.max cannot be represented as a float. Past 9007199254740992, we lose the 1's place of precision and can only specify even integers, so the bounds of the clipping become incorrect.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With