interp1 function not working properly

When I have signal of 1:130 and I interpolate it over 1:115/130:115 it returns array of only 129 values.

10 Comments

Why would you expect more than that?
size(1:115/130:115)
ans = 1×2
1 129
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
"interp1 function not working properly"
No, INTERP1 is working correctly.
However you did not check the data you are using, and so provided INTERP1 with exactly 129 values:
numel(1:115/130:115)
ans = 129
The cause is mathematics. Lets check the values by going two steps further:
V = 1:115/130:116;
X = (-4:0)+numel(V) % last five indices
X = 1×5
127 128 129 130 131
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
V(X) % last five values
ans = 1×5
112.4615 113.3462 114.2308 115.1154 116.0000
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Note how element 129 has a value less than 115.
Note how element 130 has a value greater than 115.
So your step never actually reaches the value 115 (even within binary floating point precision). There is certainly no reason to expect to get 130 elements from that operation, and the mistake has absolutely nothing to do with INTERP1.
Solution: use LINSPACE.
Alright. I went briefly through the links but I still don’t know how to fix it.
" I went briefly through the links but I still don’t know how to fix it."
V = linspace(1,115,130)
V = 1×130
1.0000 1.8837 2.7674 3.6512 4.5349 5.4186 6.3023 7.1860 8.0698 8.9535 9.8372 10.7209 11.6047 12.4884 13.3721 14.2558 15.1395 16.0233 16.9070 17.7907 18.6744 19.5581 20.4419 21.3256 22.2093 23.0930 23.9767 24.8605 25.7442 26.6279
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
V(130)
ans = 115
Or if you really want to obfuscate your code:
V = interp1([1,130],[1,115],1:130)
V = 1×130
1.0000 1.8837 2.7674 3.6512 4.5349 5.4186 6.3023 7.1860 8.0698 8.9535 9.8372 10.7209 11.6047 12.4884 13.3721 14.2558 15.1395 16.0233 16.9070 17.7907 18.6744 19.5581 20.4419 21.3256 22.2093 23.0930 23.9767 24.8605 25.7442 26.6279
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
V(130)
ans = 115
V = rescale(1:130,1,115)
V = 1×130
1.0000 1.8837 2.7674 3.6512 4.5349 5.4186 6.3023 7.1860 8.0698 8.9535 9.8372 10.7209 11.6047 12.4884 13.3721 14.2558 15.1395 16.0233 16.9070 17.7907 18.6744 19.5581 20.4419 21.3256 22.2093 23.0930 23.9767 24.8605 25.7442 26.6279
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
V(130)
ans = 115
V = 1+114.*(0:129)./129
V = 1×130
1.0000 1.8837 2.7674 3.6512 4.5349 5.4186 6.3023 7.1860 8.0698 8.9535 9.8372 10.7209 11.6047 12.4884 13.3721 14.2558 15.1395 16.0233 16.9070 17.7907 18.6744 19.5581 20.4419 21.3256 22.2093 23.0930 23.9767 24.8605 25.7442 26.6279
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
V(130)
ans = 115
But you din’t interpolate anything did you? I need to do this: interp1=(1:115,x(1:115),1:115/130:115)
and 115/130 is the problem
Edit: I basically want to turn 115 values into 130 values. But I am getting only 129.
Alright, I see. Unfortunately I don’t think I can use linspace for my case and interp1 is not working properly. What can I do?
interp1(1:115,x(1:115),linspace(1,115,130))

Thank you very much. Sometimes I can be pretty dense.

You should have already learned about quantization and truncation error when you took your college math course on linear algebra or numerical analysis. Hopefully this FAQ entry will supply your missing knowledge:

Sign in to comment.

 Accepted Answer

When you are creating the new range '1:115/130:115', it might not include the last point 115 due to floating-point arithmetic precision, leading to only 129 interpolated values instead of 130.
You can use 'linspace' function in MATLAB to generate linearly spaced vector. Here, in the following code snippet, I have used it to create 130 uniformly-spaced values between 1 and 115.
linspace(1, 115, 130)
ans = 1×130
1.0000 1.8837 2.7674 3.6512 4.5349 5.4186 6.3023 7.1860 8.0698 8.9535 9.8372 10.7209 11.6047 12.4884 13.3721 14.2558 15.1395 16.0233 16.9070 17.7907 18.6744 19.5581 20.4419 21.3256 22.2093 23.0930 23.9767 24.8605 25.7442 26.6279
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Refer to the following MathWorks Documentation to know more about 'linspace':

4 Comments

Thank you. I will try that.
Can I somehow force interp1 to include also the last number though? I tried using double here and there but it didn’t help.
Stephen23
Stephen23 on 26 Nov 2024
Edited: Stephen23 on 26 Nov 2024
"Can I somehow force interp1 to include also the last number though?"
The problem has nothing to do with INTERP1. Nothing you do with INTERP1 will make any difference to how many sample points you provide it with. Solution: use LINSPACE.
"I tried using double here and there but it didn’t help."
Correct.
Linspace doesn’t seem to work for my case: interp1=(1:115,x(1:115),1:115/130:115) I think.

Sign in to comment.

More Answers (1)

Like @Subhajyoti said, linspace would be the preferred way to get exactly the number of elements you want and to get it to end exactly in the number you want.
However, you said you want the last number to be 115 so there are two ways: either assign/overwrite the final number to 115, OR concatenate the 115 onto the existing vector.
v1 = linspace(1, 115, 130) % Best way.
% Using colon operator (less preferred than linspace():
v2 = 1 : (115/130) : 115 % 1 through 114.230769230769
% If you want the last value to be
% 115 instead of 114.230769230769 you can do this
v2(end) = 115;
% Or you can do this
v2 = 1 : (115/130) : 115 % 1 through 114.230769230769
v2 = [v2, 115] % Last two numbers are 114.230769230769 and 115.

9 Comments

"...either assign/overwrite the final number to 115"
Note that this does not change the number of elements in the vector.
"... OR concatenate the 115 onto the existing vector."
Note that in general this returns unequal spacing of the last value:
V = [1:115/130:115,115];
D = diff(V);
plot(D,'-*')
Solution: use LINSPACE.
I see, but linspace doesn’t seem to work with variable array.
I actually need solution for this: interp1=(1:115,x(1:115),1:115/130:115)
v = sym(1):sym(115)/sym(130):sym(115); disp(char(v))
[1, 49/26, 36/13, 95/26, 59/13, 141/26, 82/13, 187/26, 105/13, 233/26, 128/13, 279/26, 151/13, 25/2, 174/13, 371/26, 197/13, 417/26, 220/13, 463/26, 243/13, 509/26, 266/13, 555/26, 289/13, 601/26, 24, 647/26, 335/13, 693/26, 358/13, 739/26, 381/13, 785/26, 404/13, 831/26, 427/13, 877/26, 450/13, 71/2, 473/13, 969/26, 496/13, 1015/26, 519/13, 1061/26, 542/13, 1107/26, 565/13, 1153/26, 588/13, 1199/26, 47, 1245/26, 634/13, 1291/26, 657/13, 1337/26, 680/13, 1383/26, 703/13, 1429/26, 726/13, 1475/26, 749/13, 117/2, 772/13, 1567/26, 795/13, 1613/26, 818/13, 1659/26, 841/13, 1705/26, 864/13, 1751/26, 887/13, 1797/26, 70, 1843/26, 933/13, 1889/26, 956/13, 1935/26, 979/13, 1981/26, 1002/13, 2027/26, 1025/13, 2073/26, 1048/13, 163/2, 1071/13, 2165/26, 1094/13, 2211/26, 1117/13, 2257/26, 1140/13, 2303/26, 1163/13, 2349/26, 1186/13, 2395/26, 93, 2441/26, 1232/13, 2487/26, 1255/13, 2533/26, 1278/13, 2579/26, 1301/13, 2625/26, 1324/13, 2671/26, 1347/13, 209/2, 1370/13, 2763/26, 1393/13, 2809/26, 1416/13, 2855/26, 1439/13, 2901/26, 1462/13, 2947/26, 1485/13]
Your algorithm for generating 130 values is faulty.
w = sym(0):sym(115)/sym(130):sym(115); disp(char(w))
[0, 23/26, 23/13, 69/26, 46/13, 115/26, 69/13, 161/26, 92/13, 207/26, 115/13, 253/26, 138/13, 23/2, 161/13, 345/26, 184/13, 391/26, 207/13, 437/26, 230/13, 483/26, 253/13, 529/26, 276/13, 575/26, 23, 621/26, 322/13, 667/26, 345/13, 713/26, 368/13, 759/26, 391/13, 805/26, 414/13, 851/26, 437/13, 69/2, 460/13, 943/26, 483/13, 989/26, 506/13, 1035/26, 529/13, 1081/26, 552/13, 1127/26, 575/13, 1173/26, 46, 1219/26, 621/13, 1265/26, 644/13, 1311/26, 667/13, 1357/26, 690/13, 1403/26, 713/13, 1449/26, 736/13, 115/2, 759/13, 1541/26, 782/13, 1587/26, 805/13, 1633/26, 828/13, 1679/26, 851/13, 1725/26, 874/13, 1771/26, 69, 1817/26, 920/13, 1863/26, 943/13, 1909/26, 966/13, 1955/26, 989/13, 2001/26, 1012/13, 2047/26, 1035/13, 161/2, 1058/13, 2139/26, 1081/13, 2185/26, 1104/13, 2231/26, 1127/13, 2277/26, 1150/13, 2323/26, 1173/13, 2369/26, 92, 2415/26, 1219/13, 2461/26, 1242/13, 2507/26, 1265/13, 2553/26, 1288/13, 2599/26, 1311/13, 2645/26, 1334/13, 207/2, 1357/13, 2737/26, 1380/13, 2783/26, 1403/13, 2829/26, 1426/13, 2875/26, 1449/13, 2921/26, 1472/13, 2967/26, 115]
Whereas starting from zero gives you something that ends exactly at 115 (at least when carried out to indefinite precision.)
whos v w
Name Size Bytes Class Attributes v 1x129 8 sym w 1x131 8 sym
w has 131 values, not 130. It starts with 0, and the second element is less than 1, so if you were to discard the entries less than 1 then you would end up with only 129 values.
x = linspace(sym(1), sym(115), 130);
w1 = x(2)-x(1)
w2 = double(w1)
w2 = 0.8837
y1 = 1:w1:115
y2 = 1:w2:115
y2 = 1×130
1.0000 1.8837 2.7674 3.6512 4.5349 5.4186 6.3023 7.1860 8.0698 8.9535 9.8372 10.7209 11.6047 12.4884 13.3721 14.2558 15.1395 16.0233 16.9070 17.7907 18.6744 19.5581 20.4419 21.3256 22.2093 23.0930 23.9767 24.8605 25.7442 26.6279
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
whos y1 y2
Name Size Bytes Class Attributes y1 1x130 8 sym y2 1x130 1040 double
So if you want to use the colon operator, you need to use an increment of 38/43. Which is exactly (115-1)/(130-1)
It is hard to understand for me what you did but @Voss already helped me get the missing pieces. I am still thankful for your replay though.
Short summary:
In order to use 1:INCREMENT:115 and end up with 130 results, you need the increment to be (115-1)/(130-1)
Interesting approach. I imagine this helps with the floating point error. This wil likely work only with large fractions right?
I don't know what you mean by "large fractions".
It works fine for 7/5
A = 1:(7-1)/(5-1):115;
A(end)
ans = 115
whos A
Name Size Bytes Class Attributes A 1x77 616 double
B = linspace(1,115,77);
[~,idx] = max(abs(A-B));
A(idx), B(idx), A(idx)-B(idx)
ans = 1
ans = 1
ans = 0
I will try to use the extreme case. If I wanted to increment every 1/2 and I could not because of rounding error and therefore used step (1-1)/2-1), the results won’t be same anymore.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!