views:

260

answers:

9

If a Long Integer and a float both take 4 bytes to store in memory then why are their ranges different?

+2  A: 

No, the size of primitive data types in C is Implementation Defined.

This wiki entry clearly states: The floating-point format needs slightly more storage (to encode the position of the radix point), so when stored in the same space, floating-point numbers achieve their greater range at the expense of precision.

Prasoon Saurav
The minimum sizes are specified by the standard. BTW, the downvote wasn't me.
anon
That's true. But Dinesh has generalized the fact that `long int` and `float` takes 4 bytes.
Prasoon Saurav
+1  A: 

They are not always the same size. But even when they are, their ranges are different because they serve different purposes. One is for integers with no decimal places, and one is for decimals.

SoapBox
Not decimals; binary floating-point.
Joey
I'm trying to explain it as though to a child....
SoapBox
+2  A: 

Different way to encode your numbers.

Long counts up from 1 to 2^(4*8).

Float uses only 23 of the 32 bits for the "counting". But it adds "range" with an exponent in the other bits. So you have bigger numbers, but they are less accurate (in the lower based parts):

1.2424 * 10^54 (mantisse * exponent) is certainly bigger than 2^32. But you can discern a long 2^31 from a long 2^31-1 whereas you can't discern a float 1.24 * 10^54 and a float 1.24 * 10^54 - 1: the 1 just is lost in this representation as float.

Leonidas
A: 

This can be explained in terms of why a floating point representation can represent a larger range of numbers than a fixed point representation. This text from the Wikipedia entry:

The advantage of floating-point representation over fixed-point (and integer) representation is that it can support a much wider range of values. For example, a fixed-point representation that has seven decimal digits, with the decimal point assumed to be positioned after the fifth digit, can represent the numbers 12345.67, 8765.43, 123.00, and so on, whereas a floating-point representation (such as the IEEE 754 decimal32 format) with seven decimal digits could in addition represent 1.234567, 123456.7, 0.00001234567, 1234567000000000, and so on. The floating-point format needs slightly more storage (to encode the position of the radix point), so when stored in the same space, floating-point numbers achieve their greater range at the expense of precision.

Amit
+11  A: 

Integers are stored like this:

  • 1 bit for the sign (+/-)
  • 31 bits for the value.

Floats are stored differently, giving greater range at the expense of accuracy:

  • 1 bit for the sign (+/-)
  • N bits for the mantissa S
  • M bits for the exponent E

Float is represented in the exponential form: (+/-)S*(base)^E

BTW, "long" isn't always 32 bits. See this article.

mingos
+1.....good answer :)
Prasoon Saurav
I'd upvote, but I'm missing the word "usually" after every "are" and "is".
avakar
Integers are usually not stored with a sign bit, they are usually stored in two's complement - http://en.wikipedia.org/wiki/Two%27s_Complement
gnud
twos complement has a sign bit
anon
@avakar: could you be more explicit, plese? Do you mean the possibility of omitting the sign bit in case of using unsigned types?
mingos
"1 bit sign, 31 bits actual value" does not fit with 2s complement - all the bits are part of the actual value, even though the first bit can be used to find the sign of the number.
gnud
@gnud: agreed. I removed the word "actual" from the statement. Thanks for pointing this out.
mingos
"float" isn't always 32 bits either, IIRC. Some Crays use 40 bits
MSalters
Floats aren't always 32 bits, either. Anybody else remember Unicos? Also, some platforms, such as IBM mainframes, don't use IEEE-754 encoding. If you're looking directly at the bits, it makes a difference.Not sure how much low-level detail should be used to answer the OP, but correcting the "4 bytes" conceptual error is important.
mpez0
@MSalters: I think "floats" can also be treated as a group of data types with different precision. That would give us a range between 16 and 64 bits. But let's be honest: a plain user that checks a type's size with sizeof(whatever) sees this: 4 bytes.
mingos
A: 

Indeed a float takes 4 bytes (32bits), but since it's a float you have to store different things in these 32 bits:

  • 1 bit is used for the sign (+/-)
  • 8 bits are used for the exponent
  • 23 bits are used for the significand (the significant digits)

You can see that the range of a float directly depends on the number of bits allocated to the significand, and the min/max values depend on the numbre of bits allocated for the exponent.

With the upper example:

  • 8 bits for the exponent (= size of a char) gives an exponent range [-128,127] --> max is about 127*log10(2) = 10^38

Regarding a long integer, you've got 1 bit used for the sign and then 31 bits to represent the integer value leading to a max of 2 147 483 647.

You can have a look at Wikipedia for more precise info: Wikipedia - Floating point

David
A: 

Their ranges are different because they use different ways of representing numbers.

long (in c) is equivalent to long int. The size of this type varies between processors and compilers, but is often, as you say, 32 bits. At 32 bits, it can represent 232 different values. Since we often want to use negative numbers, computers normally represent integers using a format called "two's complement". This way, we can represent numbers from (-231) and up to (231-1). Counting the number 0, this adds up to 232 numbers.

float (in c) is usually a single presicion IEEE 754 formatted number. At 32 bits, this data type can also take 232 different bit patterns, but they are not used to directly represent whole numbers, like in the long. Instead, they represent a sign, and the mantisse and exponent of a normalized decimal number.

gnud
-1. `float` can, but does not have to be IEEE754. If it does, it doesn't have 2^32 values. There are only 2^32 bitpatterns, and some values (such as 0) can be represented by multiple bitpatterns.
MSalters
The use of the word 'values' was ambigous - I did try to explain that the different bit patterns does not map directly to numeric values. Corrected.
gnud
A: 

In general: when you have more range of values (float has up to 10^many), you have less precision.

This is what happens here. If you need integers, 32-bit long will give you more.

Pavel Radzivilovsky
A: 

In a handwavey high level, floating point sacrefices integer precision to extend its range. This is done by combining a base value with a scaling factor. For large values, a float will not be able to precisely represent all integers but for small values it will represent better than integer precision.

doron