views:

721

answers:

6

How many distinct numbers are from 1.5 x 10-45 to 3.4 x 1038 (IEE754 single precision floats)?

A: 

This isn't really programming.

bc says (for whole integers):

1.5*10^45
1500000000000000000000000000000000000000000000.0
3.4*10^38
340000000000000000000000000000000000000.0
1500000000000000000000000000000000000000000000.0-340000000000000000000000000000000000000.0
1499999660000000000000000000000000000000000000.0
Chaos
The question was edited to correct one mistake, and another was introduced. The lower limit of the range is 1.5 x 10^-45 which is not an integer. This can be seen from the title of the question.
Martin Liversage
Noted. In that case, your answer is correct - there is an infinite number of numbers between them. But this still feels like a homework question. Why are we answering it again?
Chaos
A: 

I think you mean integer numbers. And also you mean between 3.4*10^38 and 1.5*10^45 because 1.5*10^45 is larger than the other one. Anyway the answer is the same as with smaller numbers. I'll assume you want to exclude these two numbers so :

How many numbers are there between 2 and 10? The answer is 10-2-1=7. Indeed 3,4,5,6,7,8,9 are 7 numbers. So the "formula" is :

How many numbers are between a and b? The answer is b-a-1

So 1.5*10^45-3.4*10^38 -1 = 15*10^44-34*10^37 -1 = (15*10^7)10^37-3410^37 -1 =(15*10^7-34)*10^37 -1 = (150000000-34) * 10^37 -1 = 149999966 * 10^37 -1 or 1499999659999999999999999999999999999999999999

Savvas Dalkitsis
+21  A: 

Assuming that you are talking about the range in IEEE single-precision float (the 1.5 x 10^-45 is the smallest positive value it can represent that it can represent and 3.4 x 10^38 is the biggest positive value)

we would have the following possible layouts for the 4 bytes this number would occupy:

0 00000000 00000000000000000000000 = 0
0 00000000 00000000000000000000001 = 1.5 x 10^-45
......
0 11111110 11111111111111111111111 = 3.4 x 10^38
0 11111111 00000000000000000000000 = Infinity
0 11111111 xxxxxxxxxxxxxxxxxxxxxxx = NaNs

Which should give us 2139095037 numbers inbetween the two.

Andrew Y
You should probably also exclude a bunch of NaNs.
avakar
Right, I forgot about the special-case exponent == 255 in the first answer. Thanks!
Andrew Y
That's better, +1.
paxdiablo
re "absolute..." - yes it was an awkward choice of words, it was a bad translation of min(abs(x)) :-)
Andrew Y
Also, there are two zeros and two infinities, and subnormal numbers. However, the subnormals are technically without the bounds specified, and so are the zeros. So you really only have to remove positive and negative infinities and the NaN's.
WCWedin
D'oh. Within, not without. I hate when a mistake inverts the meaning of the sentence.
WCWedin
You are off by one, the answer is 2139095038 (checked programmatically, see my answer). No special cases come between these two numbers in lexicographic order.
kek444
according to the logic of your code, the number of integer numbers between 2 and 4 is (4-2)==2. Whereas there is only one integer between them: 3. So, I think you have a bug in the programmatic check.
Andrew Y
+4  A: 

I'm trying to guess what your question really is about. 1.4E-45 is approximately the smallest number (sometimes known as epsilon) that can be represented in an IEEE 754 single. The largest number is approximately 3.4E38. A single is on a computer stored in a 32 bit value and one bit used for the sign. This leaves 31 bits to represent the numbers from epsilon to the maximum value. If we assume that all possible 31 bit numbers result in a valid single then the answer to your question is 2^31 or 2,147,483,648. As it has been pointed out this assumption is not correct as some values are Not a Number or NaN.

You can read more about floating point numbers on Wikipedia

Martin Liversage
Your assumption is wrong, not every 32-bit value is available to represent a number.
paxdiablo
You are right, but since the question looks like a simple homework question I'm trying to come up with a simple answer that doesn't involve understanding IEEE 754 in details, but simply the concept of using floating point numbers to approximate real numbers on a computer.
Martin Liversage
+4  A: 

Of course, this can be done programmaticaly, for any two float numbers in general. A "lexicographic index" is the ordered index of a float number, available among other things because IEEE 754 was designed in such a way to make it easy to produce.

The basic rule is, for any two floats, if (float1 > float2) then (lexIndex1 > lexIndex2).

So calculating the number of IEEE 754 numbers between is a matter of subtracting the lexicographic indexes of the two numbers:

public class FloatUtil
{
    public static uint ToLexicographicIndex(float value)
    {
        //transfer bits to an int variable
        int signed32 = BitConverter.ToInt32(BitConverter.GetBytes(value), 0);
        uint unsigned32 = (uint)signed32;

        //(0x80000000 - unsigned32) returns 
        //appropriate index for negative numbers
        return (signed32 >= 0)
                   ? unsigned32
                   : 0x80000000 - unsigned32;
    }

    public static uint NumbersBetween(float value1, float value2)
    {
        if (float.IsNaN(value1) || float.IsInfinity(value1))
        {
            throw new ArgumentException("value1");
        }

        if (float.IsNaN(value2) || float.IsInfinity(value2))
        {
            throw new ArgumentException("value2");
        }

        uint li1 = ToLexicographicIndex(value1);
        uint li2 = ToLexicographicIndex(value2);

        //make sure return is positive
        return value1 >= value2 ? li1 - li2 : li2 - li1;
    }
}

And of course, usage in this case:

uint result = FloatUtil.NumbersBetween(1.5e-45f, 3.4e+38f);

In this case, the result is 2139081117 for these numbers in C#, since the 3.4e+38f constant expression does not compile into the maximum of the float range. However, using float.MaxValue (3.40282347E+38) as the second number gives us the expected number, 2139095038.

kek444
This is the answer to what the question should have been
Michael McCarty
Right when I wanted to add it the first time, the question was closed :)
kek444
if we apply the logic in your code to integers, 4 and 2 have (4-2) = two numbers between them. So due to this bug your answer is by one bigger than the correct one.
Andrew Y
I see what you mean. Non-inclusive interval set. However, the answer to "how many distinct numbers are from 2 to 4 (int)?" I would still answer 2.
kek444
Ok, lets state it differently - "how many distinct mornings are from Friday's morning to Sunday's morning" ?
Andrew Y
As I said, I see the point. But "how many distinct mornings are from Friday's morning to Saturday's morning?" - to answer 0...seems out of place. But it isn't the same with numbers. Imagine the question "how many distinct numbers are there from 1 to 2 (int)"? True, if the word *between* were used (and I may need to correct my method names), the answer could be zero. But it still seems to me that in this case it should be *one*.
kek444
Also note that this is a universal technique, intended to be used on variables, maybe even for epsilon checking. In that case, what should be the answer to something like ´NumbersBetween(1, 1)´?
kek444
I think we still have different interpretations - as for the question the "how many distinct numbers are there from 1 to 2 (int)" - I'd answer zero :) or two, for that matter. For the NumbersBetween 1,1 - also zero - it'd be a special case because the counts are never negative. I'm not a native English speaker (though learned it since 8), so maybe my interpretation of the question is slightly different when compared to yours.
Andrew Y
First, thanks for the technical philosophy exercise :) Now, imagine this, you have two variables x1, x2. In order to be able to differentiate them properly, the function for lexicographic indexes *shouldn't* return 0 for *both* when they are equal and when they differ by one step. I understand what you meant, I simply think that tecnically (and I consider this a technical problem, not merely logical or numeric, otherwise, why bother with a programmatic solution) zero should be returned only if they are equal. Otherwise, your points are also valid. :)
kek444
A: 

There are always uncountably many numbers between any two numbers.

Sinan Ünür
That's not true. What if I'm working over **Z** :)
GMan