Live data from Hacker News

Big-O notation explained by a self-taught programmer

justin.abrah.ms

41–50 of 80 posts

Re: Big-O notation explained by a self-taught programmer

#41
post #32

The math of Big-O isn't that hard and the article while having good intentions misses the point. Big-O is about asymptotic behaviour and the graphs are misleading in that regard (well, they're simply wrong, not misleading). There are algorithms where if you just look at the Big-O you'd think one has faster run time than the other but because the constants fall out that wouldn't be the case for any practical problem s…

As a data point, I have no idea what you just said.

Can you be more specific? :-)

You kind of need to know what a function is. That's not hard to explain either. Let's say we have f(x) = y. If I already lost you here let me know.

We say f is of O(N) (and this is a notation, not a function) if there exists two numbers, n1 and c such that for every n>n1 f(x)x. An example:

f(x) = 5 x

I can pick c = 6, n1 = 1, it's clear that for every value > 1 6x > 5 x. I just proved this function is O(N).

Note that f(x) = 1,000,000 + 5*x is also O(N), I just need to pick a large enough c and n1.

f(x) = x^2

There no c and n1 that will make the statement above true. f is not O(N).

Re: Big-O notation explained by a self-taught programmer

#42
post #31
post #10

Unfortunately, there are some misconceptions that are propagated in this article. Kudos on the effort, but some statements are just flat out wrong, such as this statement: "Big-O is all about the approximate worst-case performance". Big-O has nothing to do with worst-case, but is a bounding function. An O(n) algorithm is also O(n^2), O(2^n), etc. Those are valid bounds on the O(n) algorithm, just not the smallest.

What you said is not very correct too! Big O tells about the "order of Growth of a function or the Growth rate", that's it. It gives a larger view of the function. Seeing from 1000 feet above the ground. Link: http://web.mit.edu/16.070/www/lecture/big_o.pdf My understanding -- A bounding function is when we know the exact function and its end-points from an algorithm. We know the extremes. i.e C1 and C2. i.e a Functi…

Nothing you've said contradicts anything I wrote. I mentioned bounding functions -- you've been a bit more pedantic, but essentially you've said nothing new.

Re: Big-O notation explained by a self-taught programmer

#43
This article has way too many words and not enough math. There is, in fact, nothing scary about big O notation once you dissect it, and it's a shame that so many people seem to think otherwise.

Here's the definition: if f and g are functions (let's say real-valued functions defined on the positive reals), then we say that f is big O of g, written f = O(g), if there exists a real number y and a real number K, K > 0, such that

  f(x) 
for every x > y.

If that makes sense, then done.

Else:

The first thing to do when meeting any mathematical definition that you don't understand is to throw away parts of the definition until you do understand it, then add them back in one by one. In this case, let's forget about the constant.

New definition: For functions f, g, f is blorb of g, denoted f = blorb(g), if there is a y such that

  f(x) 
for every x > y.

"f is blorb of g" actually just means that there comes a point after which g is never smaller than f. This gives us the first ingredient of big O: we are concerned only with asymptotic behavior. f could take on immense values for small x and still be O(g) as long as f eventually becomes always smaller than g.

The reason for caring about asymptotic behavior is that we often don't care about the time complexity of an algorithm for very small problem sizes. Even the traveling salesman problem is solvable on Raspberry Pi for very small problem sizes.

Okay, I hope we understand the above definition. Now we add the constant back into the fold and see if we can make sense of it. From what I can see, the constant is there for computer scientists who want to paint with broader strokes. There can be a huge practical difference between f1(n) = 2n and f2(n) = 2000n (the difference between a computation taking a day and taking 3 years), but they're both O(n) because complexity theorists are more concerned with O(n^2) versus O(2^n) than they are with O(n) versus O(5n). (Also could be because in practice algorithms with wildly varying constant factors out in front are rarely seen?)

For an alternative to big O notation, you should check out Sedgewick and Wayne's Algorithms, 4th ed. They use something they call "tilde notation" which preserves the leading constant factor. (See: http://introcs.cs.princeton.edu/java/41analysis/)

Re: Big-O notation explained by a self-taught programmer

#44
I'm a newbie, and I enjoy articles like this as a starting point to frame the overall concept.

Like most simplifications, it's not entirely correct.

Which is why I like the comments section of HN - where I can learn more about the concept by observing how a wide variety of people explain it (and in the process correct the errors of the original article).

Re: Big-O notation explained by a self-taught programmer

#45

The post is kind of misleading because it confuses "order of magnitude" with the order of a polynomial. To make this very clear: You have two functions, x^4 and x^3. You can multiply x^3 by any constant multiple a (any number, regardless of size), and as x gets sufficiently large x^4 will be bigger than a * x^3. This is the point of evaluating asymptotic performance: as your input data approaches an infinite size, on…

> Finally, we also have small-oh notation, which is a lower bound.

Little-oh is a strict upper-bound. If `f` is `o(g)` then

  lim_(x -> inf) f(x)/g(x) -> 0.
Or something. It has been a while. If you want an asymptotic lower-bound you want big Omega (non-strict) or little omega (strict).

Re: Big-O notation explained by a self-taught programmer

#46

This sort of contributes to giving self-taught programmers a rather bad name. The writeup is good, but the idea that Big O is "scary" is just absurd. It's an elementary concept that every working programmer should be familiar with, regardless of whether they're self-taught. Algorithms are not "scary". If you can't reason about algorithms, you may not be a very good programmer yet. To be clear, I really appreciate the…

  but the idea that Big O is "scary" is just absurd.
To you. I never studied things like these in school and getting to a point of "Oh that's what that means" was long and arduous as it pertained to a lot of scientific literature.

Plain English, it seems, isn't in the tool set for a lot of very smart people who, coincidentally, feel that it's their duty to Explain All the Things. It's unfortunate that so many of them are deluded by the "x should be elementary" mindset or the like without regard to the language they use or the specificities of notation (Big-O in this case).

I wish computer scientists can be more like Neil deGrasse Tyson. http://www.youtube.com/watch?v=1ulkX-DA9BM

Re: Big-O notation explained by a self-taught programmer

#47
post #19
post #10

Unfortunately, there are some misconceptions that are propagated in this article. Kudos on the effort, but some statements are just flat out wrong, such as this statement: "Big-O is all about the approximate worst-case performance". Big-O has nothing to do with worst-case, but is a bounding function. An O(n) algorithm is also O(n^2), O(2^n), etc. Those are valid bounds on the O(n) algorithm, just not the smallest.

Note that there are other bounding functions, like bounded from the bottom (which still isn't the same thing as worst-case). See https://en.wikipedia.org/wiki/Big_O_notation#Family_of_Bachm... . Speaking of worst-case (or best-case, average-case, etc.) scenarios, how does big O notation relate? The variables inside an O() notation as far as I know refer only to the size of the input, so when we say that finding a val…

Here's an answer of mine on Quora you might find useful: https://www.quora.com/Algorithms/How-can-I-determine-whether...

There are two things going on.

First, when we talk about Big-O we're not talking about the "worst case scenario." Big-O gives us an upper bound on the worst case scenario, but the actual worst case scenario might be better. Big-O means "no worse than" not "as bad as."

When most people say Big-O they really mean Big-Θ, which does encapsulate the idea of "asymptotically equivalent, up to a constant." See my answer on Quora for more technical details.

Second, Big-O and other forms of notation used in the asymptotic analysis of functions were invented before physical computers existed. They're statements about pure functions.

When applied to the analysis of algorithms the function we're "really" analyzing isn't the algorithm. Rather, if we have an algorithm A that takes as its input a positive integer n, we're really analyzing the function "the length of time it takes algorithm A to run given input n."

The up-to-a-constant nature of Big-O notation is nice because that constant can encapsulate things like processor speed, memory access times, and so forth. This enables us to make intelligent statements about algorithms per se without reference to the underlying machine on which the algorithm might be implemented.

Even with ideal functions, this naïve asymptotic analysis has some problems. For a toy example, imagine a spiky function like this:

  f(n) = 800*n^2 if n is divisible by 1000000000
  f(n) = 400*n   otherwise
This function is not O(n) but it is O(n^2). The "worst case" behaves like O(n^2), but for "most inputs" it behaves like O(n). We can't say "f(n) is asymptotically no worse than n, up to a constant" because for infinitely many inputs it is.

Lots of algorithms behave like this in practice because we optimize for common cases perhaps at the expense of less common cases. "Common" is dictated by how our algorithm is used.

Taking quicksort as an example, let's call the algorithm Q. We want to measure its running time given an input of length n. For input x, let's say it's running time is T(x).

Well, there are many x such that len(x) == n, so what does it even mean to say "its running time given an input of length n?" Are we given a particular input of length n? A uniformly-selected-but-random input of length n? To the extent that we can, we want to be making statements about the algorithm per se, not statements about the algorithm given a particular input.

On way to answer this to ask "Given an input of length n, what's the most time my algorithm could take?" In that case we're analyzing the following function:

    W(n) = max { T(x) | x is valid input and len(x) == n }
On the other hand, maybe we care more about the average case. Perhaps we randomly pick 1,000 inputs of length n and average the running time. Now we're talking about something that looks more like a probability distribution than a discrete thing like "running time" because we've sampled the input space.

And in fact, we could calculate "expected running time given input n" in this way and graph that. We could then make Big-O like statements about that new function, which is the kind of thing folks mean when they talk about "average case."

Hope that helps!

Re: Big-O notation explained by a self-taught programmer

#48
post #32

The math of Big-O isn't that hard and the article while having good intentions misses the point. Big-O is about asymptotic behaviour and the graphs are misleading in that regard (well, they're simply wrong, not misleading). There are algorithms where if you just look at the Big-O you'd think one has faster run time than the other but because the constants fall out that wouldn't be the case for any practical problem s…

Well stated :)

Re: Big-O notation explained by a self-taught programmer

#49
One of the nice things about big-O notation from a mathematical point of view is that it allows you to avoid dealing with limits.

As everyone knows, calculus is based on limits, but when handled rigorously limits have a lot of subtle pitfalls that take a lot of work to deal with. For example, given a function f(x,y), if we want to take one limit after another, the result might depend on the order in which the limits are taken. In other words, taking limits is not commutative unless certain conditions are satisfied.

None other than the great Donald Knuth went so far as to claim that all of calculus could be taught without limits! Quoting from [1]:

"Students will be motivated to use O notation for two important reasons. First, it significantly simplifies calculations because it allows us to be sloppy — but in a satisfactorily controlled way. Second, it appears in the power series calculations of symbolic algebra systems like Maple and Mathematica, which today’s students will surely be using.

For more than 20 years I have dreamed of writing a calculus text entitled O Calculus, in which the subject would be taught along the lines sketched above."

[1] http://micromath.wordpress.com/2008/04/14/donald-knuth-calcu...

Re: Big-O notation explained by a self-taught programmer

#50
post #47
post #19

Earlier quoted context omitted.

Note that there are other bounding functions, like bounded from the bottom (which still isn't the same thing as worst-case). See https://en.wikipedia.org/wiki/Big_O_notation#Family_of_Bachm... . Speaking of worst-case (or best-case, average-case, etc.) scenarios, how does big O notation relate? The variables inside an O() notation as far as I know refer only to the size of the input, so when we say that finding a val…

Here's an answer of mine on Quora you might find useful: https://www.quora.com/Algorithms/How-can-I-determine-whether... There are two things going on. First, when we talk about Big-O we're not talking about the "worst case scenario." Big-O gives us an upper bound on the worst case scenario, but the actual worst case scenario might be better. Big-O means "no worse than" not "as bad as." When most people say Big-O the…

It sounds to me like you're mixing up two things: "worst case performance" and "asymptotic performance." You say

> Big-O is concerned with worst case performance. Colloquially, f∈O(g) means that "Eventually, f performs no worse than g."

Aren't these two different concepts? Worst case performance deals with the worst possible input of any given input size (like pathological inputs to Quicksort), while asymptotic performance is talking about sufficiently large inputs (like the vertical lines you've drawn on the graphs).

When I say that merge sorting a set of n elements is in O(n lg n), I'm saying that there's some value on the n axis beyond which n lg n >= MergeSort(n). But when I say that Quicksort is O(n^2) in the worst case, it's as if I'm talking about another other function called WorstQuicksort which when given a set of n items always takes as long as Quicksort would take to sort the most pathological set of n items, and there is some value on the n axis beyond which n^2 >= WorstQuicksort(n).

Post reply on HN