Matlab indexing uses floating point numbers? - matlab

In short, my question is:
Is a double in Matlab really a double, or is it a class with the additional property to act as an integer?
And here is the context and motivation for the question :)
>> 1:4
ans =
1 2 3 4
>> class(ans)
ans =
double
Just doing this creates a double...
>> 1.00:4.00
ans =
1 2 3 4
>> class(ans)
ans =
double
...as does this, even though it's printed as integers.
The floating point nature of the numbers only shows when greater numerical uncertainty is introduced.
>> acosd(cosd(1:4))
ans =
0.999999999999900 1.999999999999947 3.000000000000045 4.000000000000041
Is a double in Matlab really a double, or is it a class with the additional property to act as an integer?
A vector defined with "integers" (which of course really is doubles), it can be used to index another vector, which is usually a property of integers.
>> A = [9 8 7 6]
A =
9 8 7 6
>> idx = [4 3 2 1]
idx =
4 3 2 1
>> class(idx)
ans =
double
>> A(idx)
ans =
6 7 8 9
I also tried A(acosd(cosd(1:4))) which does not work.

It's just a double, but your command prompt format gives you the most compact view. Specifically,
format short
But you can change it to always display decimals, and lots of them, with
format longEng
There are many other options on the format help page.
Interestingly, you can use non-integer numbers as indexes with the colon operator, but it will warn. I would take this warning seriously as this indexing behavior is odd.
As I mentioned in my comments, the reason it is OK for MATLAB to use doubles for indexing has to do with the largest value of an integer that can be specified without losing precision in MATLAB. Double precision (64-bit) floating point numbers can exactly represent integers up to 2^53 (9,007,199,254,740,992) without losing any accuracy. The maximum array size allowed by MATLAB is far below this number, so there is no risk of indexing errors as a result of floating point precision.

In MATLAB, all numeric literals (i.e. numbers in the text of your program) are interpreted as double-precision. You must cast them explicitly to get any other type. It's worth remembering that IEEE floating point can exactly represent a wide range of integer values, up to FLINTMAX.

Related

Detailed implementation of IEEE754 in MATLAB?

In MATLAB,
>> format hex; 3/10, 3*0.1
ans =
3fd3333333333333
ans =
3fd3333333333334
>> 3/10 - 3*0.1
ans =
bc90000000000000
Is this result predictable? i.e. I can follow some rules of floating point arithmetic, and get 3/10 = 3d3333333333333, 3*0.1 = 3d3333333333334 again by hand.
The rules are:
In MATLAB, unless specified otherwise (via constructors), all literals have double precision in the sense of IEE754 standard: http://www.mathworks.com/help/matlab/matlab_prog/floating-point-numbers.html
All arithmetic operations are executed according to the usual precedence rules: http://www.mathworks.com/help/matlab/matlab_prog/operator-precedence.html
When mixing numeric types with double in an arithmetic operation, MATLAB converts the double to the other numeric type before executing the operation—as opposed to C, for example, which does the other way around.
By using these rules you can pretty much predict the results of any arithmetic expression (always little endian memory layout, bit patterns are two's complement for signed integers and IEEE754 for floats). The alternative is to let MATLAB apply the rules for you; the results will be consistent and repeatable.
The reason is that when creating the binary representation for 0.1 a roundup has occurred, introducing a small error:
>> 0.1
ans =
3fb999999999999a
There should be infinitely many of those 9s in the end but we cut it and round up the last digit. The error is small but becomes significant when you multiply by 3
>> 3*0.1
ans =
3fd3333333333334
When correctly calculated by division this last digit shouldn't be 4:
>> 3/10
ans =
3fd3333333333333
It is interesting to see that this error is not big enough to cause a problem when we multiply by some other number smaller than 3 (the threshold is not exactly 3 though):
>> 2.9/10
ans =
3fd28f5c28f5c28f
>> 2.9*0.1
ans =
3fd28f5c28f5c28f

Multiplication of integer-valued matrices in MATLAB

What is the best way to multiply integer-valued matrices in MATLAB?
I was surprised to learn that the following isn't accepted behavior:
>> x = int64([1, 2])
>> x * x'
Error using *
MTIMES is not fully supported for integer classes. At least one input must be scalar.
To compute elementwise TIMES, use TIMES (.*) instead.
I can always convert to double and back again. Is this the best solution? I'm using R2013b.
In this simple case, you could get by with using
sum(x.*x)
It seems times (.*) is supported properly for integer matrices, although mtimes ( *) is not.
For general matrix multiplication: let A and B be two matrices with suitable sizes so that A*B exists. Since times and sum are supported for integers, you can generalize the above trick, usingbsxfun and sum to compute all entries of the product matrix as follows.
Edit: As noted by #July, you need the 'native' flag in sum in order to keep the result of integer type. Thanks also for pointing out a problem that was caused by squeeze, now corrected by using a second permute.
permute(sum(bsxfun(#times, A.', permute(B, [1 3 2])), 1, 'native'), [2 3 1])
For example:
>> A = int64([1 2; 3 4])
A =
1 2
3 4
>> B = int64([5 7 9; 6 8 10])
B =
5 7 9
6 8 10
>> permute(sum(bsxfun(#times, A.', permute(B, [1 3 2])), 'native'), [2 3 1])
ans =
17 23 29
39 53 67
Anyway, the fastest alternative seems to be double(A)*double(B).
MATLAB does not support integer matrix-matrix multiplication due to the lack of industrial support.
MATLAB uses BLAS (more specifically, Intel's implementation of BLAS, i.e. MKL) to do matrix multiplication. At present, BLAS does not natively support multiplication of integer matrices. However, a good news is that MKL 2018 adds initial support for integer matrices. (cf. this slides)
As for your question, if you aim at performance and your matrices are not too small, sum(x.*x) is inferior to int64(double(x)*double(x.')).
Use native only when you are sure that overflow and underflow will not happen.
One extra note is that although native flag can keep the type of return value the same as that of input value. It may suffer from integer overflow or underflow. Check with the following snippet.
sum(int8(-ones(300,1)), 'native') % ans = -128 (of type int8)
sum(int8(ones(300,1)), 'native') % ans = 127 (of type int8)
sum(int8(ones(300,1))) % ans = 300 (of type double)
Although single and double can also overflows and underflows, they happens less frequently.

two values are seemingly the same, yet matlab says the aren't [duplicate]

This question already has an answer here:
What is -0.0 in matlab?
(1 answer)
Closed 9 years ago.
I cannot explain this. I have two variables having the same value, yet they are not identical. Can anybody tell me what I'm missing here?
>> y
y =
3.4000
>> x
x =
3.4000
>> y==x
ans =
0
>> whos x
Name Size Bytes Class Attributes
x 1x1 8 double
>> whos y
Name Size Bytes Class Attributes
y 1x1 8 double
It's really puzzling for me and I swear it's not a joke.
It's because of floating point precision. Try
format long g
and then look at x and y again. It's better to compare x-y to some small tolerance value rather than doing an equality test on floating point numbers
You're comparing float values, an activity which doesn't work quite how you think in basically any language, due to how floating-point values are handled by computers.
The solution to this is generally to instead test whether the different between the values is less than some small threshold.
See here for a Matlab-related discussion of this.

Matlab floor bug? [duplicate]

This question already has answers here:
Why is 24.0000 not equal to 24.0000 in MATLAB?
(6 answers)
Closed 5 years ago.
I think I found a bug in Matlab. My only explanation is, that matlab calculates internally with other values than the ones which are displayed:
K>> calc(1,11)
ans =
4.000000000000000
K>> floor(ans)
ans =
3
Displayed code is an output from the Matlab console. calc(x,y) is just an array of double values.
MATLAB uses the standard IEEE floating point form to store a double.
See that if we subtract off a tiny amount from 4, MATLAB still diplays 4 as the result.
>> format long g
>> 4 - eps(2)
ans =
4
In fact, MATLAB stores the number in a binary form. We can see the decimal version of that number as:
>> sprintf('%.55f',4-eps(2))
ans =
3.9999999999999995559107901499373838305473327636718750000
Clearly MATLAB should not display that entire mess of digits, but by rounding the result to 15 digits, we get 4 for the display.
Clearly, the value in calc(1,11) is such a number, represented internally as less than 4 by just a hair too little that it rounds to 4 on display, but it is NOT exactly 4.
NEVER trust the least significant displayed digit of a result in floating point arithmetic.
Edit:
You seem to think that 3.999999999999999 in MATLAB should be less than 4. Logically, this makes sense. But what happens when you supply that number? AH yes, the granularity of a floating point double is larger than that. MATLAB cannot represent it as a number less than 4. It rounds that number UP to EXACTLY 4 internally.
>> sprintf('%.55f',3.9999999999999999)
ans =
4.0000000000000000000000000000000000000000000000000000000
What you got was a value really close to but lower than 4, and even with format long Matlab has to round to the 15th digit to display the number.
Try this:
format long
asd = 3.9999999999999997 %first not-9 #16th digit
will print 4.000000000000000. Anyone who doesn't know the actual value of asd based on what gets visualized would guess it is at least 4, but running
asd >= 4
gives 0, and so floor(asd) returns 3.
So is a matter of how Matlab rounds the displayed output, the true value stored in the variable is less than 4.
UPDATE:
if you go further with the digits, like 18x9:
>> asd = 3.999999999999999999
asd =
4
>> asd == 4
ans =
1
asd becomes exactly 4! (notice it doesn't display 4.000000000000000 anymore) But that's another story, is no more about rounding the number to have a prettier output, but about how the floating point arithmetic works... Real numbers can be represented up to a certain relative precision: in this case the number you gave is so close to 4 that it becomes 4 itself. Take a look to the Python link posted in the comment by #gokcehan, or here.
I won't go over the problem, instead I will offer a solution: Use the single function:
B = single(A) converts the matrix A to single precision, returning that value in B. A can be any numeric object (such as a double). If A is already single precision, single has no effect. Single-precision quantities require less storage than double-precision quantities, but have less precision and a smaller range.
This is only meant to be a fix to this particular issue, so you would do:
K>> calc(1,11)
ans =
4.000000000000000
K>> floor(single(ans))
ans =
4

matlab double comparison

I am trying to compare an array of doubles to a scalar double for equality, but equality is never recognized under certain circumstances. I suspect that this has to do with the way the double is represented (e.g., 1.0 vs 1.00), but I can't figure it out.
For instance, I have generated an array composed of thousands of double values, the last few of which at some instant in time are given by
10.6000
-11.0000
10.2000
22.6000
3.4000
If I test for equality to 10.2 (or 10.2000) by the command array==10.2 (or array=10.2000), I return an array of 0s. If I place the values shown into an array manually (e.g., array=[10.6000 -11.0000 10.2000 22.6000 3.4000]), then the command is successful (i.e., array==10.2 returns 0 0 1 0 0). Could someone please explain why the equality succeeds if I input the values manually, but fails if the array is generated in the context of a program? I am able to rectify the comparison failure by using an approximate rather than an exact comparison (e.g., (array<10.20001) & (array>10.19999)), but this seems unsatisfying.
Edit: The values in the array are generated by iterative addition or subtraction of a constant double (e.g., 0.2). The modulus of this array by 0.2 should therefore be everywhere equal to 0. In fact, the modulus of each element is equal to either 0 or 0.2, as shown below for the above sequence of numbers in the array:
mod(array,0.2)
...
0.2000
0
0.2000
0.2000
0
Again, if the values are placed in an array manually and the modulus is taken, the expected value of all 0s is obtained.
The reason is MATLAB truncated the numbers in the array to preserve only 4 digits after the decimal point when displaying,. That is, the real value of your array may be [10.600000000001, -10.99999999999, ...]. You are right, this is due to the internal representation of floating-point numbers in computer, which may cause tiny errors in the computations.
Personally I think there are two solutions, one is approximate matching like you did, while the other is to round the array up first (say, with this tool from FileExchange), and then do exact matching.
Something is probably in single precision somewhere, and double elsewhere. The binary representation of e.g. 10.2 in each is different as they terminate after a different number of bits. Thus they are different:
>> if (single(10.2) == 10.2) disp('honk'); end
>> if (single(10.2) == single(10.2)) disp('honk'); end
honk
You'll need to check for equality within some small difference:
eps = 0.001;
result = abs(array-10.2) < eps;
You can find the precision used in an array using whos:
>> whos A
Name Size Bytes Class Attributes
A 1x2 8 single
Create a MATLAB function file that will accept a modulo values (from 3 to 9; that is Z3 to Z9) and
will output the least possible value describe by the modulo conditions.
Sample Simulation:
Z = [ 3 4 5 ]; % Modulo Z3, Z4, and Z5
r = [ 2 1 4 ]; % Remainder Values
Least Possible Value is 29.
The Z inputs must be an array matrix ... where in you can type any number from 3 to 9 .... and you can type 3,4,5,6,7,8,9 in any order, in any pairings or groupings ...
The r inputs should be equal to the number of z inputs too...
the output should yield the least possible value though modulo conditions...