0

At first glance, my question could seem a bit odd; but casting a double to a float value is not what i want. Since when you cast it, you just lose some precision with respect to the rules defined IEEE-754 and can't achieve actual mapping of a double value to the range of float; it is useless. The following expression works, but it is very very expensive when you have a great amount of input:

float mappedVal = (float)((val * MAX_FLOAT_VALUE + 1) / MAX_DOUBLE_VALUE);

Can I approximate the result to the "mappedVal" mentioned above via some sort of bitwise operations to speed-up the very same computation?

iliTheFallen
  • 466
  • 7
  • 16
  • 2
    please give examples of input and output data – Nikolay Kuznetsov Mar 15 '13 at 09:01
  • 1
    You say that because casting loses precision with regard to IEEE-754, it's useless. Then you ask about bitwise operations to "approximate the result"? Just cast it if you want an approximation. – mjuarez Mar 15 '13 at 09:03
  • 1
    Only guessing, but I think it will underflow – Bohemian Mar 15 '13 at 09:06
  • Ok. for example, whenever you have a double value which is greater than the MAX_FLOAT value and cast it by running an instruction like "float mappValue = (float)myDoubleValue;"; it is approximated to MAX_FLOAT value; i.e. it is exactly equalized to MAX_FLOAT value. This is not a mapping; but just an approximation. – iliTheFallen Mar 15 '13 at 09:12
  • Is MAX_FLOAT_VALUE equal to Float.MAX_VALUE and MAX_FLOAT_VALUE equal to Double.MAX_VALUE? Is there a cast still missing? It testet your expression under these assumptions for `val == 1`: the result is 0. – Claude Mar 15 '13 at 09:20
  • Yes; MAX_FLOAT_VALUE = Float.MAX_VALUE and MAX_DOUBLE_VALUE = Double.MAX_VALUE. aaa yes you are also right about that there is an explicit cast around the right-hand side expression to float. I've just fixed it; thanks for the correction! – iliTheFallen Mar 15 '13 at 09:24
  • Is your question "is the above mapping a *replacement for casting*" or is your question "how to speed up the above *expression*"? To speed up you can precompute `1/MAX_DOUBLE_VALUE` and `MAX_FLOAT_VALUE/MAX_DOUBLE_VALUE`. – Claude Mar 15 '13 at 09:32
  • Can you reveal what sort of mapping you want ? Because there are (a lot) more doubles than floats you're going to have to accept that many doubles map to the same float, what is the rule you want to apply ? If, that is, it's not a type cast. – High Performance Mark Mar 15 '13 at 09:32
  • I don't understand the question. You want to convert a double to a float but you don't want the loss of precision that necessarily entails? Not a real question. – user207421 Mar 15 '13 at 09:42
  • Yes yes! exactly i want to map some of doubles to the very same float value! It is like in opengl for example, you map (let's say) an integer value to the range of [-1.0, 1.0] by "(2*val + 1) / MAX_INTEGER_VALUE. In fact, my case is very similar to that one! – iliTheFallen Mar 15 '13 at 09:42
  • 2
    `float` values **cannot** represent all the same values as `double` values. It is mathematically impossible, since `float` has fewer bits. Therefore, you **must** lose information. Many transformations are theoretically possible. Some would preserve precision in a specific range but be very inaccurate outside it, some would transform dynamic range but lose a lot of precision, and so on. To get an answer, you **must** specify the characteristics of the transformation you want. – Eric Postpischil Mar 15 '13 at 11:52
  • A double value ranges from MIN_DOUBLE_VALUE to MAX_DOUBLE_VALUE right?; likewise does any float from MIN_FLOAT_VALUE to MAX_FLOAT_VALUE. I want to map any value which is defined in a greater range(double) to a value defined in a smaller range(float). Most of the values in greater range(double) will eventually be mapped to the same value in smaller range(float); but it'll still preserve relative distance to max and min values. Let's say i have a value defined in range 0-9 and i want to map it to a range 0-1; in turn all values lesser than 4 will be mapped to 0 whereas the rest will be to 1. – iliTheFallen Mar 15 '13 at 13:37
  • Michael, btw i am so sorry i didn't see your message; but your solution seems feasible actually! I'll give it a try! Thank you! On the other hand; you know i just wanted to know if there is a way to achieve it via bitwise operations; but you know speed-up is speed-up:) – iliTheFallen Mar 15 '13 at 13:45

2 Answers2

0

I'm not sure what you're trying to achieve, since some double values are far outside the range of float.

But if you're willing to risk losing values that are too big for float, try this:

float f = new Double(val).floatValue();

Edit: which is exactly the same as casting to float. :)

Vegard
  • 4,802
  • 1
  • 20
  • 30
  • Do you think this is fast enough? instead of multiplying and dividing it on ALU; it uses some elegant solution like playing around with bits of double value to convert it into a float value? – iliTheFallen Mar 15 '13 at 09:46
  • Actually, I checked the Java source code, and this is the exact same thing as casting to float. – Vegard Mar 15 '13 at 09:49
  • Owww:( No mapping then... Anyway; really thanks for paying attention to my question. It seems i should play around the IEEE-754 double and float value representations to figure out a way to map a double value to range of [MIN_FLOAT_VALUE, MAX_FLOAT_VALUE] in a fast and efficient way... – iliTheFallen Mar 15 '13 at 09:52
  • Like I said, I don't really understand what you're trying to achieve. By stuffing a 64 bit value into 32 bits you will in many cases run into either loss of precision or simply have a value that is too large for a float variable. Like mjuarez stated, casting is probably as close as you can get. – Vegard Mar 15 '13 at 09:53
0

This maps a double precision value into the float that has the same highest 32 bits:

float mappedVal = Float.intBitsToFloat((int)(Double.doubleToLongBits(val)>>32));

The arithmetic interpretation of this operation is a little complicated though, parts of the exponent are mapped into the mantissa...

Joni
  • 108,737
  • 14
  • 143
  • 193
  • Well very fantastic :).. If it really maps a double value to the range of float type; it is really great and what i am looking for. Very thanks indeed. I'll give it a try and let you know of what output i really get. – iliTheFallen Mar 17 '13 at 06:49
  • When i compare the result with the one i obtain from the very first equation i'd written in my post; it seems they are not equal to each other. On the other hand, it computes some reasonable values. Well what is the logic behind what you said? – iliTheFallen Mar 18 '13 at 19:11
  • Well. i use the formula: float mappedValue = (float)(doubleValue * MAX_FLOAT_VALUE + 1) / MAX_DOUBLE_VALUE; and the result is completely different than yours in magnitude. – iliTheFallen Mar 19 '13 at 08:26
  • This mapping is based on the binary representation of floating point numbers: it keeps the most significant bits and tosses out the least significant. Since the number of exponent bits differs between float and double you will see a wide difference in magnitude. – Joni Mar 19 '13 at 19:06
  • Aaaa, i think, i see what you mean. give me sometime to do some experiements; then i can tell you more about the effects of your solution on my problem. Apart from that, thanks for being interested in my problem Joni. – iliTheFallen Mar 20 '13 at 07:36