gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

C/C++ > Floats

#3893 - darkcloud - Wed Mar 12, 2003 12:37 am

I know, I know, you shouldn't use floats on the gba, but put that beside. Say I have a float, and its value is 0.9999999887044263 etc, but I only want to use the first 6 digits and have the 7th rounded. How would I do this?

For example, like when you use printf, if you printf-ed that float by doing something like printf("%f", float), the output would be 1 because by default, %f would output the first 6 digits. But if I were to use printf("%.20f", float), it would print the exact number.

So I want to only use the first 6 digits of a float. I don't know if there's an obvious answer or not, but I can't figure it out, so I hope someone can help.
_________________
Maybe in order to understand mankind, we have to look at the word itself: "Mankind". Basically, it's made up of two separate words - "mank" and "ind". What do these words mean ? It's a mystery, and that's why so is mankind.

#3898 - Quirky - Wed Mar 12, 2003 8:52 am

Why would you want to do that anyway? If it's to print out a value, then just use sprintf, if it's to compare 2 values then you are asking for trouble.

Anyway, one way to round to a certain precision, if you really must, is to do this...

(int)(x * precision + 0.5) / precision

That is, multiply by the precision, add 0.5, truncate and then divide back down by the precision value. But I wouldn't recommend you ever use that on the GBA! :-)

#3920 - jenswa - Wed Mar 12, 2003 8:44 pm

or you can convert the float to a string and substring the digits you
want to get your 6 decimals and then convert it back to float.

#3924 - darkcloud - Wed Mar 12, 2003 11:32 pm

Ok well I tried Quirky's method but I ran into a problem. When I divide the truncated number by my precision, the resulting float seems to have some junk numbers.

Say my int value is 70717, and I divide it by 100000. The resulting float is not 0.70717, but more like 0.70717007483920 etc. Why are these junk numbers added?
_________________
Maybe in order to understand mankind, we have to look at the word itself: "Mankind". Basically, it's made up of two separate words - "mank" and "ind". What do these words mean ? It's a mystery, and that's why so is mankind.

#3927 - ampz - Thu Mar 13, 2003 3:00 am

Because all decimal float numbers can't be exactly expressed as binary float numbers and vice versa. It's a matter of mathemathics. If you read into the basics of floats you'll understand.
Float math is by nature not 100% exact, it's only exact to a certain number of decimals. Integer math on the other hand is always exact.

Actually, on a sidenote, the exact same float operation can give you two slightly different results on two different processor types.

If you could pleeease tell us what you need this for we could solve your problem.

#3929 - Paul Shirley - Thu Mar 13, 2003 3:21 am

removed

Last edited by Paul Shirley on Sun Mar 28, 2004 9:55 pm; edited 1 time in total

#3930 - pelrun - Thu Mar 13, 2003 3:21 am

Try writing the exact value pi down on paper. Of course, it's impossible because in decimal it's an irrational number, and so would take an infinite amount of paper. So you make an approximation.

But say you created a new numbering system, called pi-imal. To convert to pi-imal from decimal you just divide the decimal number by pi, and to convert back to decimal you multiply by pi. Then, if you wanted to write down the value of pi in pi-imal you just have to write down "1"!

The same goes for floats. There are just some numbers (ok, an infinite amount) that CANNOT be represented using a finite amount of RAM. But because floats are stored in binary, the set of rational and irrational numbers is completely different to that in decimal.

So whilst 0.70717 is only 5 decimal places long, it is MANY MANY MORE "binary places" long. And so it gets rounded off - *in binary*. And this nice round binary number just happens to be MANY MANY decimal places long!

Usually this is ok, because you round off to a small number of decimal places at some point and that error falls below the threshold. You just happen to be trying to grab as many decimal places as you can, and you end up noticing the approximation.

If you're really desperate to have "absolutely perfect" decimal numbers, then you need to store your numbers as strings, and do decimal arithmetic on them "manually". This is usually called "bignum" or "arbitrary precision" arithmetic. It takes up much more memory and is far slower than the CPU's native binary math.

#3933 - darkcloud - Thu Mar 13, 2003 3:39 am

OK well that clears a lot up for me. I guess I should look more into the whole float precision topic. The purpose for this is for a calculator application I'm trying to write for the GBA. I wrote my own trig functions and I wanted the output of these to be rounded to the 6th digit because, for example, sin(90)=1, but my sin function outputs something like .99999987etc, which, when rounded is 1. So that's why I wanted only the first six digits of a float.

So anyone have any suggestions of how I should do this?

Thanks for all the help so far though.
_________________
Maybe in order to understand mankind, we have to look at the word itself: "Mankind". Basically, it's made up of two separate words - "mank" and "ind". What do these words mean ? It's a mystery, and that's why so is mankind.

#3934 - tepples - Thu Mar 13, 2003 5:00 am

darkcloud wrote:
OK well that clears a lot up for me. I guess I should look more into the whole float precision topic. The purpose for this is for a calculator application I'm trying to write for the GBA.

What kind of input are you using? A calculator needs at least 17 keys.

Quote:
I wrote my own trig functions and I wanted the output of these to be rounded to the 6th digit because, for example, sin(90)=1, but my sin function outputs something like .99999987etc, which, when rounded is 1.

If you're making a calculator, you'll need to use double precision rather than single precision. Most calculators with a sin() function have a ten-digit display.

Quote:
So anyone have any suggestions of how I should do this?

First find the greatest power of 10 less than or equal to the absolute value of your number (do this with a binary search in a lookup table). For example, for 62635, return 10000 (10^4); for 0.0513, return 0.01 (10^-2). Store the exponent, and divide the number by the power of 10 (e.g. 62635 becomes 6.2635 * 10^4). You have just converted the number into scientific notation.

Then multiply the number by 10^(n - 1) for a display of n digits. For instance, on a 10-digit TI-36x emulation, multiply by one billion (10^9). (You can optimize this step by combining it with the division by the power of 10.) Then round to the nearest integer (x = floor(x + 0.5)). Then convert this to a decimal numeral, slap a decimal point in the proper place if the display is not in scientific mode, and print it.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#3936 - Paul Shirley - Thu Mar 13, 2003 5:25 am

removed

Last edited by Paul Shirley on Sun Mar 28, 2004 9:55 pm; edited 1 time in total

#3972 - darkcloud - Fri Mar 14, 2003 4:52 am

Ok, well I've gotten everything straightened out. The outputs of my functions are coming out exactly as I want.

Thanks to everyone.

@Tepples: Thanks for the suggestion. As for the input, I was planning to do it all on screen, using sprites or a background for keys. I know it might be a bit slow to enter data into a calculator, but its shouldn't be too much of a hassle if the keys are mapped out nicely. I'll probably include some hot-key-type buttons for basic operations like add, subtract, multiply, divide, or maybe I'll let the user map out the buttons to the specific operations they would like to perform.
_________________
Maybe in order to understand mankind, we have to look at the word itself: "Mankind". Basically, it's made up of two separate words - "mank" and "ind". What do these words mean ? It's a mystery, and that's why so is mankind.

#3985 - ampz - Fri Mar 14, 2003 1:28 pm

Hey, use the 'keyboard advance' ;-)