What is the advantage of linspace over the colon ":" operator?
Asked Answered
M

3

22

Is there some advantage of writing

t = linspace(0,20,21)

over

t = 0:1:20

?

I understand the former produces a vector, as the first does.
Can anyone state me some situation where linspace is useful over t = 0:1:20?

Michelemichelina answered 10/10, 2014 at 5:47 Comment(3)
One would be that you can specify the number of elements, N needed with linspace, so if N is given you save yourself the trouble of calculating the stepsize. BTW a good way to use the former case would be t=linspace(0,20,N).Ertha
I guess you meant to write t=linspace(0,20,20). Please edit the question to help future readers.Ferland
linspace(0, 20, 21) would be a better match for 0:1:20.Azaria
F
24

It's not just the usability. Though the documentation says:

The linspace function generates linearly spaced vectors. It is similar to the colon operator :, but gives direct control over the number of points.

it is the same, the main difference and advantage of linspace is that it generates a vector of integers with the desired length (or default 100) and scales it afterwards to the desired range. The : colon creates the vector directly by increments.

Imagine you need to define bin edges for a histogram. And especially you need the certain bin edge 0.35 to be exactly on it's right place:

edges = [0.05:0.10:.55];
X = edges == 0.35

edges =   0.0500    0.1500    0.2500    0.3500    0.4500    0.5500
X =  0     0     0     0     0     0

does not define the right bin edge, but:

edges = linspace(0.05,0.55,6);   %// 6 = (0.55-0.05)/0.1+1
X = edges == 0.35

edges =   0.0500    0.1500    0.2500    0.3500    0.4500    0.5500
X =  0     0     0     1     0     0

does.

Well, it's basically a floating point issue. Which can be avoided by linspace, as a single division of an integer is not that delicate, like the cumulative sum of floting point numbers. But as Mark Dickinson pointed out in the comments: You shouldn't rely on any of the computed values being exactly what you expect. That is not what linspace is for. In my opinion it's a matter of how likely you will get floating point issues and how much you can reduce the probabilty for them or how small can you set the tolerances. Using linspace can reduce the probability of occurance of these issues, it's not a security.

That's the code of linspace:

n1 = n-1
c = (d2 - d1).*(n1-1) % opposite signs may cause overflow
if isinf(c)
    y = d1 + (d2/n1).*(0:n1) - (d1/n1).*(0:n1)
else
    y = d1 + (0:n1).*(d2 - d1)/n1
end

To sum up: linspace and colon are reliable at doing different tasks. linspace tries to ensure (as the name suggests) linear spacing, whereas colon tries to ensure symmetry

In your special case, as you create a vector of integers, there is no advantage of linspace (apart from usability), but when it comes to floating point delicate tasks, there may is.

The answer of Sam Roberts provides some additional information and clarifies further things, including some statements of MathWorks regarding the colon operator.

Florous answered 10/10, 2014 at 6:6 Comment(12)
+1 for showing the difference between colon and linspace, where one works and another doesn't.Ferland
The == 0.35 reasoning is a bit dodgy: it's mostly just luck that that equality happens to work - the floating-point errors just happened to cancel out in that case. E.g., what happens in that comparison if you replace 0.35 with 0.15 instead?Azaria
It's a question of how likely the issue is. Do you have a better example?Florous
No: I wouldn't suggest relying on any of the computed values being exactly what you expect. I don't think that's what linspace is for. The biggest advantage of linspace for me is that you know both how many points you're going to get, and what spacing (up to numeric error) those points are going to have. In contrast, floating-point errors can leave it unpredictable what the last point of (e.g.) 0.05:0.1:0.55 actually turns out to be.Azaria
@MarkDickinson I will try to include your suggestions and clarify my answer after work ;)Florous
@thewaywewalk The colon operator does not work in the way you suggest - it does not add up a cumulative sum of increments. Rather, it ensures symmetry of the output vector by adding increments to the start point and subtracting decrements from the end point until it gets to the midpoint. See mathworks.co.uk/matlabcentral/answers/… for more detail.Barboza
@thewaywewalk PS your comment about linspace being more reliable is quite misleading - both linspace and colon are perfectly reliable at doing different tasks. linspace tries to ensure (as the name suggests) linear spacing, whereas colon tries to ensure symmetry.Barboza
@MarkDickinson The colon operator does not leave it at all unpredictable what the last point will be, as it works forward from the supplied start point and backwards from the end point.Barboza
@SamRoberts I included your comment. I din't expected that is question get's so much attention and maybe I'm not able to explaine verything properly. Please feel free to edit details.Florous
@SamRoberts: Ah, interesting. That wasn't what I was expecting from the documentation. So what does 0.0:1.0:10.5 do?Azaria
@SamRoberts: I see that the colon operator is more DWIMmy than I realized. Thanks for the correction!Azaria
@MarkDickinson If you follow the link in my comment, you'll see that it includes a file colonop.m, which is a .m file that implements the exact algorithm used by the built-in colon operator. You can read through to see exactly what the colon operator does for 0.0:1.0:10.5.Barboza
B
10

linspace and the colon operator do different things.

linspace creates a vector of integers of the specified length, and then scales it down to the specified interval with a division. In this way it ensures that the output vector is as linearly spaced as possible.

The colon operator adds increments to the starting point, and subtracts decrements from the end point to reach a middle point. In this way, it ensures that the output vector is as symmetric as possible.

The two methods thus have different aims, and will often give very slightly different answers, e.g.

>> a = 0:pi/1000:10*pi;
>> b = linspace(0,10*pi,10001);
>> all(a==b)
ans =
     0
>> max(a-b)
ans =
   3.5527e-15

In practice, however, the differences will often have little impact unless you are interested in tiny numerical details. I find linspace more convenient when the number of gaps is easy to express, whereas I find the colon operator more convenient when the increment is easy to express.

See this MathWorks technical note for more detail on the algorithm behind the colon operator. For more detail on linspace, you can just type edit linspace to see exactly what it does.

Barboza answered 10/10, 2014 at 10:27 Comment(4)
This answer should clarify some more things ;) +1Florous
The link to the MW site is broken. Do you have an updated link, or some other information on the colon operator? It's not my experience that it works backward, the last element can be included or not depending on the step size.Banneret
@CrisLuengo That’s annoying, looks like they took the technical note down. I’ll try to find another reference.Barboza
Detailed information about how the colon operator works: https://mcmap.net/q/587908/-how-does-the-colon-operator-work-in-matlab/7328782Banneret
E
9

linspace is useful where you know the number of elements you want rather than the size of the "step" between them. So if I said make a vector with 360 elements between 0 and 2*pi as a contrived example it's either going to be

linspace(0, 2*pi, 360)

or if you just had the colon operator you would have to manually calculate the step size:

0:(2*pi - 0)/(360-1):2*pi

linspace is just more convenient

For a simple real world application, see this answer where linspace is helpful in creating a custom colour map

Endodontics answered 10/10, 2014 at 6:0 Comment(1)
Can you fix the off-by-one error so that the two expressions correspond? Either linspace(0, 2*pi, 361), or 0:(2*pi - 0)/359:2*pi.Azaria

© 2022 - 2024 — McMap. All rights reserved.