Actually in the theoretical world, the cost is always O(1) because the hash function computation always takes constant time. You are restricting yourself to a machine model with bits, which is not assumed by big-O notation.
But it doesn't even work in that theoretical world: as n gets arbitrarily large, you've used up all the keys and they have to start sharing buckets, forcing you to iterate over O(n) of them -- although the constant on that is only logarithmic in the size of the hash function output space (aka linear in the size of hash output)!
Generally you move to a larger hash table long before you get that much key collision. Which is a big cost once, but the amortized cost doesn't change much.
But in general with these discussions, you assume that certain operations are constant on your "machine". For instance, addition is usually considered constant even though it isn't if your numbers are larger than your machine's word size.
In the case of the hash tables, you assume your hash is constant, even if, as you note, it isn't really. But the fact is, the coefficient for the O(log N) term is so small, that it doesn't really offer any useful insight towards the performance of the algorithm.
>Generally you move to a larger hash table long before you get that much key collision. Which is a big cost once, but the amortized cost doesn't change much.
No, it's a big cost every time you pass a threshold, which happens an infinite number of times, because big-O assumes numbers can be arbitrarily large.
>But in general with these discussions, you assume that certain operations are constant on your "machine". For instance, addition is usually considered constant even though it isn't if your numbers are larger than your machine's word size.
As long as the max number size is orthogonal to the number of elements n, you can assume a bound on the time for an addition operation, and then it becomes a constant in your run-time expression with respect to n. No sleight-of-hand there.
>In the case of the hash tables, you assume your hash is constant, even if, as you note, it isn't really. But the fact is, the coefficient for the O(log N) term is so small, that it doesn't really offer any useful insight towards the performance of the algorithm.
All true, but the spec for big-O doesn't say "assume away stuff that doesn't matter in practice". It says, "as n gets arbitrarily large". When you make inconsistent, varying assumptions between problems, you're not doing STEM anymore; you're doing memorization, the kind of thing STEM isn't supposed to be like.
If "the" definition of big-O consistently included a definition that "we never have to deal with more than 2^64 elements", that would be fine. Instead, we have to memorize "the right answers" for when you can and can't assume that, and only then does O(1) for hash lookup pop out.
And if you really just care about in-practice, then you can no safely assume that a typical balanced binary tree lookup takes fewer ops than e.g. SHA256.
> No, it's a big cost every time you pass a threshold, which happens an infinite number of times, because big-O assumes numbers can be arbitrarily large.
Yes, it happens repeatedly. But it's not a big cost on every operation. Instead, it's a bigger and bigger cost, that happens more and more rarely. Averaged over the run, it's insignificant.
> As long as the max number size is orthogonal to the number of elements n, you can assume a bound on the time for an addition operation, and then it becomes a constant in your run-time expression with respect to n.
But it isn't necessarily orthogonal. As you deal with more and more elements, it's probably true that those elements will get correspondingly large. But maybe they won't be! The point is, we've decided that that is not a significant issue, since it's not part of most algorithms involving addition.
> All true, but the spec for big-O doesn't say "assume away stuff that doesn't matter in practice"
Of course it does. Everything is built on axioms and assumptions; things that are relevant to the problem, and things that are not.
> When you make inconsistent, varying assumptions between problems, you're not doing STEM anymore; you're doing memorization, the kind of thing STEM isn't supposed to be like.
I have no idea where this came from, but it's neither relevant nor accurate. Every STEM field requires a significant amount of memorization, and any application of a STEM field requires understanding what is relevant to the discussion at hand, and what is not.
The point of any system—Big O included—is to understand a problem. The cost of the hashing operation isn't relevant for understanding the performance characteristics of hash tables. Maybe your hashing function is O(log N), and so lookups are O(log N). Maybe your hashing algorithm is O(N^2), and so your lookups are O(N^2). Neither tells you anything about how your hash will perform.
Edit: clarify and fix error.