Can someone provide examples in Layman's terms?
The basic types in C are just there to standardize a single unit of memory (a block of bits) that can be used to store a value. We all know that a computer uses bits as its basic unit of information, however a bit is too small to be useful in and of itself, by defining different types we define different blocks of bits and how to interpret them. When we say "int a", the compiler knows that we are dealing with a basic, signed binary number, and knows the amount of memory it needs to set aside to store that number.
The biggest issue is that the exact size definitions are system dependent and not defined in the specifications.
-
A float and double are both implementations of floating point values in C. floating point numbers are a way to implement decimal and fractional values, of any magnitude in binary and also streamline their arithmetic. It is essentially a binary version of scientific notation. Imagine writing the number 3.14159 In decimal, The mantissa here would be 314159 and the exponent would be -5. You could define a simple function that takes the two numbers (stored in binary) and prints out their combined decimal value, your program could therefore store all decimal numbers as two different numbers in binary, and use its own functions to add them together, print them etc. However, C streamlines this process by giving you a simple container that does all that work for you behind the scene. A floating point standard describes how you would encode the mantissa and exponent into a single binary number. In C, the only difference between a float and a double is the amount of memory set aside to store your number, and thus the greater range and precision of the numbers that you can store. The benefit of this is that you can also describe large integer numbers, for instance, you would need 32 bits to write the number "4 billion" explicitly in binary, but you only need 8 to do the same in floating point (4 x 109). However, you would not be able to write the number 4,123,456,789 as an 8 bit floating point or even a 32 bit floating point number (as you still need to encode the exponent), but it will fit perfectly well in a 32 bit int.
-
A char and int are just basic binary numbers, their only difference being in length (potentially). A character is defined as the smallest unit of data necessary to hold a single text character for that architecture, this is a bit abstractly defined, but for most computer today running x86 platforms, a char is defined as 8 bits (although, on unicode systems it could be 16 bits). An integer is another basic binary number, but it is required to be at least 16 bits long (typically it is either 32 or 64 on modern systems). So a 8 bit char is capable of encoding 256 unique characters, or a number between 0-255 (or a number between -127 and 128) the difference is only in how you interpret the collection of bits. An 32 bit int can store a number between 0 and slightly over 4 billion, or you could half that range and use it to represent a number between (roughly) -2 billion and 2 billion
On some systems, the size of an int may be the same as the size of float, from the memory point of view they are just collections of bits, however the processor will interpret the values differently, and will actually use different circuits to add two numbers together if they are floats vs if they ints.
I don't know about examples, but they are simply different primitive types in C. Both double and float are for floating point numbers (e.g., numbers with fractional parts) and int and char are for whole numbers.
The reason there is more than one type for each class of number is because they take up a different amount of memory, and can therefore me bigger / more precise. There are actually quite a few more besides the four you've listed.
Sorry if this seems like a basic question, but I've been learning C over the past several weeks. In some of the tutorials I've been using, I've noticed some of the instructors just use int/float while others tend to default to double when declaring floating point variables.
Is there any sort of best practice in terms of deciding what size variable to use?
The main reason is the same reason we often prefer to use integer fractions instead of fixed-precision decimals. With rational fractions, (1/3) times 3 is always 1. (1/3) plus (2/3) is always 1. (1/3) times 2 is (2/3).
Why? Because integer fractions are exact, just like integers are exact.
But with fixed-precision real numbers -- it's not so pretty. If (1/3) is .33333, then 3 times (1/3) will not be 1. And if (2/3) is .66666, then (1/3)+(2/3) will not be one. But if (2/3) is .66667, then (1/3) times 2 will not be (2/3) and 1 minus (1/3) will not be (2/3).
And, of course, you can't fix this by using more places. No number of decimal digits will allow you to represent (1/3) exactly.
Floating point is a fixed-precision real format, much like my fixed-precision decimals above. It doesn't always follow the naive rules you might expect. See the classic paper What Every Computer Scientist Should Know About Floating-Point Arithmetic.
To answer your question, to a first approximation, you should use integers whenever you possibly can and use floating point numbers only when you have to. And you should always remember that floating point numbers have limited precision and comparing two floating point numbers to see if they are equal can give results you might not expect.
As you can see in here the different types each have their own size.
For example, when working with big databases, an int or float may double up the required size.
The default choice for a floating-point type should be double. This is also the type that you get with floating-point literals without a suffix or (in C) standard functions that operate on floating point numbers (e.g. exp, sin, etc.).
float should only be used if you need to operate on a lot of floating-point numbers (think in the order of thousands or more) and analysis of the algorithm has shown that the reduced range and accuracy don't pose a problem.
long double can be used if you need more range or accuracy than double, and if it provides this on your target platform.
In summary, float and long double should be reserved for use by the specialists, with double for "every-day" use.
There is rarely cause to use float instead of double in code targeting modern computers. The extra precision reduces (but does not eliminate) the chance of rounding errors or other imprecision causing problems.
The main reasons I can think of to use float are:
- You are storing large arrays of numbers and need to reduce your program's memory consumption.
- You are targeting a system that doesn't natively support double-precision floating point. Until recently, many graphics cards only supported single precision floating points. I'm sure there are plenty of low-power and embedded processors that have limited floating point support too.
- You are targeting hardware where single-precision is faster than double-precision, and your application makes heavy use of floating point arithmetic. On modern Intel CPUs I believe all floating point calculations are done in double precision, so you don't gain anything here.
- You are doing low-level optimization, for example using special CPU instructions that operate on multiple numbers at a time.
So, basically, double is the way to go unless you have hardware limitations or unless analysis has shown that storing double precision numbers is contributing significantly to memory usage.