- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
You know, they could have just used Youd's constant to figure that out. For more information visit: http://www.youdzone.com/youds_constant.html
Admin
Admin
It'd be better with a switch/case.
Admin
See http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious for a table lookup version (among others) of integer log2
Admin
WTF? That's just log_10(2). This constant does nothing!
Admin
Admin
He's saying that the difference between a and b when a == b requires zero bits.
a - b + 1 = 1
log_2(1) = 0
Ergo, the number of bits needed to represent (a - b) is zero. Yes, his wording is a bit weird, but that is (I believe) what he meant. In a real application of this, you probably want to reserve at least one bit for a zero value to indicate that there actually IS a value (and that it is zero), but maybe the person programming works for Oracle and doesn't think distinguishing between those two things is very important.
Admin
Since the program processes gigabytes of data using Fortran, assuming x86 would be major WTF.
Captcha: darwin If Darwin was right, Fortran would be extinct
Admin
I'm not sure what you're getting at here. If you're saying the big O of an algorithm doesn't matter, you're an idiot. Just because you don't understand computer science doesn't mean it's not important. Anyway, the previous poster wasn't arguing that the original code was correct, just that the "+ 1" in the correct formula from previous comments was necessary.
Admin
Maybe a BCD floating point would solve most accuracy problems. (Yes I know of at least one "system" (actually, it's a calculator) that uses BCD for floating point math.)
Admin
Um, the inputs (min and max) are integers. Therefore the logs only need to be accurate to one part in 2^31, which is 10 significant digits.
So maybe I was a bit hasty in dismissing the need for double precision, but for this application floating point works just fine.
Admin
That's not FORTRAN! Why isn't everything indented to column 7? What's with the :: ? end do?
Sheesh! You kids today...
Admin
Not having Fortran readily available, I just translated the code snippet into Perl, and it seems to give incorrect results (too small by 1) for many possible inputs, starting with f(4) = 2 instead of 3. As was mentioned before, the correct final operation is ceil(), not int() or floor(). I think the biggest WTF is that a routine that obviously does not work properly has been allowed to remain in software used by hundreds of people for years.
Admin
i get the feeling that it's precisely because of WTFs like this that FORTRAN isn't extinct. the system becomes so complicated that a complete re-write (plus all the testing that that entails) becomes such an un-appealing task that no-one wants to take it on.
Admin
Admin
Wow. Lots that do not work with the shifting etc.
static int Bits(long range) { int nbits = 1; while ((range >>= 1) > 0) { nbits++; } return nbits; }
Works for all positives. (You still need 1 bit to represent zero)
Admin
There's still the fact that the original code almost all of the time. So the code ain't that bad. Just because a tiny bit of refactoring of the logic is in order it seems a bit crazy to see the need to enumerate in detail the reasons why it needs to be changed in the light of some of its now known failure conditions. Classic case of 20/20 hindsight. Most bugs look like a WTF when you find the root cause of it.
In general this list seems like some sort of vindictive move for being tasked with tracking this difficult bug down. In my experiance this happens when some programmer is tasked with helping find a bug when he/she normally doesn't do that sort of thing and is used to writing new code most of the time. Bug-fixers (maintainers) see this sort of thing all the time but going off on the original programmer is a no-no at most shops.
Admin
yup. watch out for the 72 character cut-off, too (after all, if if that was enough for my grand-parents' generation, it's certainly enough for me now)
Admin
Uhm... All you guys pasting C code to solve this problem: You know about the ffs() function, right? (OK, it's UNIX-specific, but still...)
Admin
Anyone under the age of thirty who has used FORTRAN needs to get a life!
Admin
To represent the number 256 you need 9 bits. To represent a range of 256 different numbers, 0 to 255 for example, you only need 8.
Admin
oi! some of us don't get much choice in the matter!
Admin
How is knowing the position of the least significant set bit helpful? ffs(n)=1 for every odd n.
Admin
Since when are integers only allowed to be 32 bits?
Try ceil(log((1UL << 63) + 1)/log(2)) on a 64-bit machine!
Captcha: darwin (survival of the precisest).
Admin
Admin
For most languages, (C, Pascal, Java, etc) the loop is the natural approach. However, in my experience Fortran users tend towards mathematical solutions, so here's my attempt:
double drange drange = dabs(max, min) nbits = int((dlog(drange + 1.0d0) / dlog(2.0d0)) + 1.0d-10)
As others have noted, double precision is accurate to 53 bits, so it will preserve the 31 bit (positive) integer accuracy. You need to stay in double precision (e.g. abs() is single precision). The +1.d-10 rounding constant is bigger than any possible double precision error (~10^-16) but smaller than 2^-31 ~ 2*10^-9.
And, depending on the likely values of max and min, may be faster than the loop solution.
Admin
One again, the comments to the Daily WTF make it abundantly clear why these WTFs are so common.
Admin
As bad as it is, this overstates the problems.
Using double precision DLOG doesn't really fix the problem, although it does make it more unlikely.
Adding 1 to a real (instead of 1.0 or even 1.0D0) requires converting integer 1 to real. Any fortran worth its salt will do this at compile time, so there's no difference there. Same goes for 2.0D0. All of these can be exactly represented in single proecision real.
The real problem is using floating-point numbers here instead of the ISHIFT intrinsic or a table lookup.
Admin
Not likely. Express 1/3 exactly using BCD. You can't. Only way to exactly represent some real numbers is to use alternate bases. 1/3 cannot be exactly represented as a floaing point in base 10. However, 0.1 in base 3 does.
Typically BCD calculators are used for an arbitrary precision and scale. You'll typically see these used for currency instead of floats. (most databases have this datatype, as well, check out 'decimal').
Admin
For a really cool solution, see http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
(C only, requires bitwise or and bit shift). Took me a while to understand it :)
For fortran, I'd take the loop or even the unrolled loop over the floating point calculations - because the latter is so much harder to prove correct.
captcha:muhahaha
Admin
before anyone gets verbally medieval on me for the "C only": I change that to "from the two languages given, and assuming that fortran indeed can't do bitwise or shift operations".
phew.
Admin
Probably a stupid question, but when would one need to determine the number of storage bits programatically?
Admin
The real WTF to me is why would you need to know the minimum number of bits to store a number? I can see what's the smallest data type that'll hold this number, but why the exact number of bits?
Admin
Consider. You have a range of numbers between A and B, you know how many you have, and you need to know the fewest bits to represent each of them.
Now, suppose B=A. How many different values do you have to encode? 1. How many bits are you going to use to represent them..?
As a note, I wouldn't be bothering to post this, but you made such a meal of your derision for the poster you were replying to, despite the fact the only ignorance on show was your own. You might want to think about that next time you indulge in playground point'n'laugh.
Admin
However, you're spot on about maintainers; in fact the feeling I usually get when I manage to track down a weird bug isn't vindictiveness, but euphoria. It's like doing a crossword puzzle. I suspect I'm in a relatively rare group of people who actually likes maintenance programming; I'm at my happiest with a big pile of bugs to fix and no external interference, especially as I'm learning my way around a codebase.
Admin
The most common application is in data compression, or at least that's where I've run into it. Suppose you want to store a very large set of numbers between 719 and 782 in the smallest number of bytes.
By doing this sort of analysis, you can determine that 6 bits are all you need for each value. By packing those 6-bit values as closely as possible, you can fit 10 of them into 8 bytes. The more straightforward solution of using a byte for each value requires 25% more space.
Admin
I find only three problems with this snippet.
The logic of the function is obvious:
Maybe it would have been more clear to write: range= max-min+1; Instead of adding one in the call to the log().
I guess this function was used for some kind of compression. Then the real WTF is, that there were GB of data [intact].
Admin
The important thing to keep in mind is that accuracy degrades whenever you subtract two numbers that are close together and are real numbers that cannot be represented exactly in your hardware. Unfortunately that normally means any serious number crunching as it is not merely transcendantals that fall in that category but rather the vast majority of decimal fractions that cannot be represented exactly as binary floating point numbers.
Admin
BCD floating point should be used for all financial calculations and most calculations where the end result is shown to the user. The problem is that there aren't that many good implementations (Java didn't get it right until Java 5), and I don't think there is a hardware BCD floating point implementation even today.
Admin
Some old C++-code of mine that uses binary search to do the same thing (a different kind of WTF!, I guess):
And then, to find log2:
Admin
Well, my fortran is non-existant. So I'll throw in some perl instead and since I need the POSIX module, it should be possible in C
find number of Bits required to represent a value
and the max value those bits can represent
use POSIX;
#$Val = some integer value
$log2 = log(2); $logV = log($Val);
($frac, $int) = modf($logV/$log2);
$bits = ($int + ceil($frac)); $max = pow(2, $bits);
The inability of floating point math to properly represent integers is largely irrelevant. If there is a fractional result from the modf() then we have to add 1 to $int to obtain the necessary number of bits. If fortran can do a modulus operation with real numbers then you may be able to test for a mod greater than 0 and add 1.
Admin
Why do you people think this is such a WTF? It's not QUITE correct but not off the deep end, either. So it uses floats, which is probably not optimal, but you people seem to be struggling with the basic MATH. You people write code?
To figure the number of bits required to represent a number N:
nbits = ceil(log(N+1)/log(2)).
What's so damn hard? And the +1 is not a kludge, it's what MAKES IT WORK. Find a value of N where it doesn't give the right answer, I dare you.
God you people suck at math.
And negative values of N don't count. Why? Don't be stupid -- a negative value in two's complement always has a 1 in the highest bit, so the number of bits required to represent any negative value is always the same.
Admin
Admin
To figure the number of bits required to represent a number N:
nbits = ceil(log(N+1)/log(2)).
??? You must be the guy that wrote the original code!
(1) Why the +1 in there ? (2) If you take out the +1, log(N) / log(2) might end up being 7.9999999 or 8.0000001, depending on the precision of the math. taking the ceiling of those numbers gives different results. So how is this adequate?
Well, they do, as log blows up. it would be nice if the program could tell the user about this, or maybe continue, instead of getting a run-time error.
Admin
Assuming N is a positive integer, the number of bits is either
1 + floor( log(N) / log(2) )
or
ceil( log(N+1) / log(2) )
The former is better suited to bit-twiddling implementations though, so should be considered superior.
Admin
Uh, to make it correct? Think of the case N=1... It's not in there because of rounding issues, it's in there because IT'S NOT RIGHT without it.
So you're saying, doing things the wrong way leads to wrong answers? "Brillant" insight, there.
BTW, I wrote a program which checks every value in the 32 bit integer domain, and the answer is right in ALL CASES, using IEEE floating point math. What more do you want?
Admin
If there are a groups of apples numbered 2,3,4,5,6,7 and you wanted to know how many there are, that would be: (7 - 2) + 1 = 6
Taking the +1 out of the log function doesn't change the precision of the results. It changes what problem you are solving. You're still likely to get "rounding errors." However, by taking the ceil()ing of the result, you get an accurate integer power of two which answers the question. The operation isn't reversible if the desired result is a number of bits--since we can't have a fractional bit.
They don't count, since N is a range whose value is returned from abs(), which returns either zero or a positive number. There will be no blowing up of log, as only legal values will ever reach it.
Admin
Ooh, maths... pretty... wouldn't the "a" of a log be an exp?
Come to think of it it's amazing what you can still develop without using either logs or antilogs.
Admin
But if that's the case, the function would be clearly understandable and easily verified as correct, much much better than the original WTF. So what if it takes log(N) operations to get the result for input N? We are talking about very important data here.
Admin
Almost, but you've got a bug in your bit shifting. And it can be done on one line.