iam0a1
Level 0


« on: May 04, 2013, 10:36:05 am » 

I'm going through the Unity 3.x Game Development Essentials book, which I am finding very helpful, but there is a code listed in here that I find confusing. This is written in Unityscript, but in this book the C# example also lists these numbers as floats as well. EX. 1 var power : float = 1500; Should this actually be : var power : int = 1500; EX. 2 var moveSpeed : float = 5; why not : var moveSpeed : int = 5; Why does the book consider this a float? Can you just consider any value a float since there is a understood decimal value of .0 at the end of every number? If so, when does int actually come into use?



Logged




milo_dercius


« Reply #1 on: May 04, 2013, 10:43:05 am » 

Just because they are not assigning a value with a decimal does not mean that they should be using an int. Making them floats or doubles allows the math that gets done with them to have a decimal answer later on. Int is more precise and is used when you are not going to have decimals in your calculations.



Logged




BleakProspects


« Reply #2 on: May 04, 2013, 10:50:56 am » 

Integers are a subset of *real* numbers. Floating point (float, double, etc.) is a way of representing a large amount real numbers using a fixed amount of memory. Integers (int, long, short, etc.) are a totally different way of representing *integer* numbers using a fixed amount of memory. In this way, floating point numbers are *totally incompatible* with integer representations of number. In most programming languages, "literals" (the actual numbers you put down, like '5') can be interpreted in a variety of different ways depending on context. The number 5 might be interpreted as an integer, a character, a real number, or even an enum depending on the context in which it is used. So saying float v = 5; Is really telling the compiler "Make a block of memory 32 bits wide and fill it with the floating point representation of the number 5". It is exactly the same as writing float v = 5.0; or float v = 5.00000000; or float v = 5e1; Wheras if you say this: int v = 5; You are saying to the compiler "give me a block of memory 32 bits wide initialized with the integer representation of 5". But the floating point representation and the integer representation in memory for the number 5 are completely incompatible. If you tried this instead: // Error! int v = 5.0; The compiler has no idea what to do, because there is no integer representation of "5.0". The addition of the ".0" at the end turns the integer literal "5" explicitly into a real number literal. For this reason, in code, an integer equal to 5 is not the same as a floating point number equal to 5.


« Last Edit: May 04, 2013, 10:56:30 am by BleakProspects »

Logged




iam0a1
Level 0


« Reply #3 on: May 04, 2013, 11:01:50 am » 

Thanks guys, really helpful. I understand it now.



Logged




Sar


« Reply #4 on: May 04, 2013, 12:43:06 pm » 

However, it's probably worth noting that you can still (in most languages, I'm pretty sure it's the case for UnityScript and it's definitely the case for C#) do an equality check between ints and floats: int v = 5; if (v == 5.0) { // This code will execute ... }
It's also worth noting that floating point numbers are the work of the devil, because they actually only store an approximation of the number you give them. If you ever have any weird accuracy problems in your game that you can't track down, they probably came from your use of floating point numbers. But we still use them because they're faster than fixedpoint arithmetic. ;_;



Logged




ham and brie


« Reply #5 on: May 04, 2013, 01:05:34 pm » 

It's also worth noting that floating point numbers are the work of the devil, because they actually only store an approximation of the number you give them. If you ever have any weird accuracy problems in your game that you can't track down, they probably came from your use of floating point numbers. But we still use them because they're faster than fixedpoint arithmetic. ;_;
Fixed point numbers are also approximations. The reason we use floating point is that difference between one number and the next is relative to how large the number is. With fixed point you can get greater (but still not perfect) precision for the same number of bits, but only if the number is within a particular range, so you have to write your code according to what range the values will be in to have that advantage.



Logged




xgalaxy


« Reply #6 on: May 04, 2013, 10:40:35 pm » 

Not sure exactly on C# but in C/C++ doing: float foo = 5; is technically creating an int and converting it to a float. Eg, the compiler is actually doing this: float foo = (float)5; To avoid that, create foo like so: float foo = 5.f; If you simply did the following: float foo = 5.0; Then the compiler is technically creating a double and converting it to a float. The reason this becomes important is because if your doing math, instead of just simple assignment, the compiler will convert the values to the higher order type and this will be slower than if you used the correct types. For example if you were to do the following: float foo = 5.f; float bar = foo * 2.0 + 1; Then foo and 1 get converted to a double, then the math calculations are made, and then the result is converted back to a float. So not only do you have unwanted type conversions, you also have slower double precision math calculations and potential loss of precision. And if that wasn't enough you may also have a higher likelihood of bugs due to unwanted conversion from signed to unsigned values. So the take away from this is that even though the compiler will, in most cases, implicitly do the type conversion automatically, you should err on the side of being explicit because often times the compiler is going to do something you didn't intend.



Logged




Sar


« Reply #7 on: May 05, 2013, 12:48:10 am » 

Fixed point numbers are also approximations.
Yes and no. Fixedpoint numbers are absolutely precise if the number you put into them is within the range of precision that type can hold, which is a known constant which you can work to; floatingpoint numbers are precise almost at random  generally because of the results of calculations you do; two calculations at the same magnitude which produce the same number sometimes come up with different results using floats, for example*. With fixedpoint arithmetic, you know the exact limitations of the numbers in advance and if you know that your number space fits entirely within those limitations, you can be happy that fixedpoint maths is going to absolutely be good enough for you; with floats, you can't trust the damn things further than you can throw them. And they're incorporeal. * Example, from C#, responses indented by me. 12/0.4 30.0 1.2/0.4 2.9999999999999996 1.2*2.5 3.0
I know why that's happening, and I expect you know why that's happening, but I also expect that to your average newbie who has to ask questions like the one starting this thread, that's going to read as "the computer is broken". Unfortunately C# doesn't have a standard fixedpoint type to use instead. Which is enough of a grounding as any that floats are good enough for most purposes. The builtin Decimal type is widely considered a fixedpoint type but in fact is just another floatingpoint type!



Logged




ham and brie


« Reply #8 on: May 05, 2013, 01:34:37 am » 

* Example, from C#, responses indented by me. 12/0.4 30.0 1.2/0.4 2.9999999999999996 1.2*2.5 3.0
I know why that's happening, and I expect you know why that's happening, but I also expect that to your average newbie who has to ask questions like the one starting this thread, that's going to read as "the computer is broken". Have you actually tried doing those calculations with a binary fixed point type?



Logged




Sar


« Reply #9 on: May 05, 2013, 02:47:55 am » 

Have you actually tried doing those calculations with a binary fixed point type?
Off the top of my head, I think the only fixedpoint type I have on my PC right now is in SQL, so excuse the verbose example: declare @x numeric(38, 37) declare @y numeric(38, 37) declare @result numeric(38, 37)
select @x = 1.2 select @y = 0.4 select @result = @x / @y
select @result
 3.0000000000000000000000000000000000000
There are several languages which have 'extra precision numeric' types which are just fancy floats, like C#'s Decimal type  are you sure you're not thinking of those?



Logged




ham and brie


« Reply #10 on: May 05, 2013, 03:51:09 am » 

That's a 17 byte (!) decimal type. I said binary fixed point type.
Decimals types make sacrifices to favor decimal numbers. Decimals are special to humans (e.g., you chose 12/10 and 4/10), so they're appropriate for some applications, but not for general calculations in games. You can have not only slower calculations and more memory used, but also larger errors in the results.
Even without a binary fixed point type, you could still try out the equivalent integer maths.



Logged




Sar


« Reply #11 on: May 05, 2013, 02:40:48 pm » 

... appropriate for some applications, but not for general calculations in games. You can have not only slower calculations and more memory used, but also larger errors in the results.
Wasn't that my point in the first place? Leaving aside that "larger errors in the results" is really only the case if you go outside of the bounds of the type, which frankly is a problem with every type in one form or another! You have to use floats in games for a lot of things, because fixedpoint arithmetic isn't fast enough... but it's still worth being aware of the limitations with floats so you're not too surprised when  say  (1.2/0.4 >= 3) evaluates to false. Which it does, and by proper mathematics it shouldn't. A lot of people think "floating point number" means "real number" and because of that they can't work out what's wrong with their code. (Whether you like it or not your game code will use decimal numbers, unless you do all your operations with bitwise operators and shifts.) Yes, a lot of these problems are due to the fact that there is a set of rational numbers that can't be exactly represented in binary and there is a different set of rational numbers that can't be exactly represented in decimal. But the practical point is that you have to be more careful with floating point numbers than pretty much every other type you encounter in daytoday games programming. (Integer maths [scaled up by a fixed magnitude] naturally works and doesn't work, depending on how your integer divisions are calculated.)



Logged




ham and brie


« Reply #12 on: May 06, 2013, 12:03:31 am » 

Leaving aside that "larger errors in the results" is really only the case if you go outside of the bounds of the type, which frankly is a problem with every type in one form or another! Not sure what you're trying to say here. It's the case if a calculation produces an approximate result. Which is what you're complaining about with floats... You have to use floats in games for a lot of things, because fixedpoint arithmetic isn't fast enough... Speed is not why we use floats over fixed point. but it's still worth being aware of the limitations with floats so you're not too surprised when  say  (1.2/0.4 >= 3) evaluates to false. Which it does, and by proper mathematics it shouldn't. A lot of people think "floating point number" means "real number" and because of that they can't work out what's wrong with their code. And you seem to be implying fixed point is different in this respect, but it's not. (Whether you like it or not your game code will use decimal numbers, unless you do all your operations with bitwise operators and shifts.) I mean decimal in the sense of base10. You might use base10 for human readable representations of numbers (such as float literals in source code), but all operations are performed in base2. Yes, a lot of these problems are due to the fact that there is a set of rational numbers that can't be exactly represented in binary and there is a different set of rational numbers that can't be exactly represented in decimal. This is relevant to why your example worked better with a decimal type (which says little about fixed point vs floating), but it's not particularly important in general calculations. But the practical point is that you have to be more careful with floating point numbers than pretty much every other type you encounter in daytoday games programming. And fixed point involves at least as much care. (Integer maths [scaled up by a fixed magnitude] naturally works and doesn't work, depending on how your integer divisions are calculated.)



Logged




Sar


« Reply #13 on: May 06, 2013, 12:58:31 am » 

This is relevant to why your example worked better with a decimal type (which says little about fixed point vs floating), but it's not particularly important in general calculations.
It's relevant because literally all of the fixedpoint types  both builtins and extensions people have written because they want the functionality  that I've come across recently in modern programming languages have been fixeddecimalpoint rather than fixedbinarypoint types. Which work without conversion problems but are much slower than floating point arithmetic. Largely because fixedbinarypoint types are... kind of useless compared to floats? But my main point  which you seem to be ignoring in favour of a desperate attempt to prove that something I didn't say is wrong  was that you have to be aware that floating point numbers are not the same as real numbers. *Sigh*. I really don't see much point continuing this discussion.



Logged




ham and brie


« Reply #14 on: May 06, 2013, 02:11:21 am » 

It's relevant because literally all of the fixedpoint types  both builtins and extensions people have written because they want the functionality  that I've come across recently in modern programming languages have been fixeddecimalpoint rather than fixedbinarypoint types. Which work without conversion problems but are much slower than floating point arithmetic. Even if that's been your experience so far, fixed point shouldn't be confused with decimal types. Try googling fixed point library and see what you find. Largely because fixedbinarypoint types are... kind of useless compared to floats? No, they definitely have uses. But my main point  which you seem to be ignoring in favour of a desperate attempt to prove that something I didn't say is wrong  was that you have to be aware that floating point numbers are not the same as real numbers.
I'm not ignoring that. That's fine. I'm not disagreeing with that. I'm not replying because I want to prove a point. I was genuinely trying to be helpful in pointing out that fixed point is also approximate, because what you wrote implied it avoided a problem which it doesn't actually deal with.



Logged




ThemsAllTook


« Reply #15 on: May 06, 2013, 11:41:02 am » 

With fixedpoint arithmetic, you know the exact limitations of the numbers in advance and if you know that your number space fits entirely within those limitations, you can be happy that fixedpoint maths is going to absolutely be good enough for you; with floats, you can't trust the damn things further than you can throw them. And they're incorporeal.
(I'm coming into this discussion a bit late, pardon the severalpostsback quote) I used to think the same thing about floats, but this page really helped me understand their anatomy and demystify them: http://en.wikipedia.org/wiki/IEEE_7541985After studying that a bit and running a few tests, floats make a lot more sense, and errors in them are fairly predictable. However, error can vary slightly across CPU architectures  although the same calculation will always give the same result on one CPU, it might have one bit of difference on another, which can be enough to throw off an entire simulation in some cases. Binary fixed point numbers (never heard of a decimal fixed point implementation before, that sounds crazy!) solve that problem by using integer arithmetic which is 100% consistent everywhere, at the cost of precision, performance, and easy access to math functions like sin(), sqrt(), etc.



Logged




Sar


« Reply #16 on: May 06, 2013, 12:01:24 pm » 

errors in them are fairly predictable
In my experience, the problems most people will encounter with floats are more that they don't expect the errors in the first place.



Logged




