## rosegarden-devel

 [Rosegarden-devel] Re: tempo rounding error? float vs. double? From: Nicholas Bailey - 2004-07-26 09:36:03 ```Hi Silvan. Don't panic! This is one of the most common reasons my C-with-EE students screw up when writing C/C++ :) I've not got the source to hand because I'm working from my laptop, so I can't give you a specific answer, but it sounds as if you've made the mistake of believing what the C++ program prints out to be the actual number represented. I'm only rock-steady on C rules, not C++ (am I showing my age here? :) but: 1. It's unlikely that you'll need more than a float (6 sig fig) for this application unless you're doing anything remarkably ill-conditioned. 6 sig figs gives you an error of around about 100msec over the whole of the Ring Cycle. 2. Unless storage is a big problem, you'll be wanting to use doubles anyway. Why? Because in C (for C++ I'd have to check) all of the calculations involving floats are done at double precision anyway, and then cast back to floats before assignment. I recall things are less clear cut in C++, but I'd have to check up how exactly. In C, anyway, this makes x=a+b (double x, a, b) *faster* than if a and b are floats, and faster still than if x, a and b are all floats. There are compiler flags to force fp ops to be done in floats rather than doubles, but they are rarely used. As for printing things out, the trouble here usually arises from things that are completely easy to represent in decimal mapping onto recurring bicimals. So 1/4 = 0.25 = %0.01 (% for decimal) which is easy, but try that with 1/5 = 0.2 = ? Because the ? is infinitely recurring, you truncate it when it's stored. If you store it as a float, it's further away from 1/5 than if you store it in a double. When you print 5*what_you_stored, you get, say, 1.00000000001 in a double and 0.999999 in a float (I just made those numbers up). Now you also have to cope with the default field width and so on for the printing. The a better solution might be to specify a reasonable field width and resolution in the program, forcing it not to be silly. nick@...:~\$ cat trunc.c #include main() { float x = 1.0f/10.0f; double y = 1.0/10.0; printf("%.12f\t%.12f\n", 10.0f*x, 1.0f-(10.0f*x)); printf("%.12f\t%.12f\n", 10.0*y, 1.0-(10.0*y)); } nick@...:~\$ gcc trunc.c nick@...:~\$ ./a.out 1.000000014901 -0.000000014901 1.000000000000 -0.000000000000 nick@...:~\$ Note that, even with doubles, the answer is -0 (i.e., not 0!) (embarrassingly, on the Powerbook I'm using right now, dh176-197:~ nick\$ gcc trunc.c dh176-197:~ nick\$ ./a.out 1.000000000000 0.000000000000 1.000000000000 0.000000000000 but I expect I could find some numbers that would screw it up! Markov's dual AMD-K7, for the record, debian unstable, gcc 3.3. The P4's running the same compiler version) Solution: always use sprintf(string, "%g6.2", number) if you want to be sure what gets formatted (or using the C++ spelling with << and so on). And never compare doubles or floats with == or you are asking for trouble! "God created integers: all else is man's handiwork" (Karl Weierstrass http://scidiv.bcc.ctc.edu/Math/Weierstrass.html) Nick/. PS: Thanks for your earlier pointers about our pitch tracker integration ideas. We are still working on it. N/. ```