Java: increment through Float.floatToIntBits? - java

I need to increment a float value atomically. I get its int value by calling Float.floatToIntBits on it. If I just do an i++ and convert it back to float, it does not give me the expected value. So how would I go about it?
(I'm trying to create an AtomicFloat through AtomicInteger, hence this question).
EDIT: here's what I did:
Float f = 1.25f;
int i = Float.floatToIntBits(f);
i++;
f = Float.intBitsToFloat(i);
I wanted 2.25, but got 1.2500001 instead.

The reason is that the bits you get from floatToIntBits represents
sign
exponent
mantissa
laid out like this:
Repr: Sign Exponent Mantissa
Bit: 31 30......23 22.....................0
Incrementing the integer storing these fields with 1 won't increment the float value it represents by 1.
I'm trying to create an AtomicFloat through AtomicInteger, hence this question
I did precisely this in an answer to this question:
Java: is there no AtomicFloat or AtomicDouble?
To add functionality to increment the float by one, you could copy the code of incrementAndGet from AtomicInteger (and change from int to float):
public final float incrementAndGet() {
for (;;) {
float current = get();
float next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
(Note that if you want to increment the float by the smallest possible value, you take the above code and change current + 1 to current +Math.ulp(current).)

The atomic part can be implemented atop compareAndSet for a wrapper class as shown in the link of aioobe. The increment operators of AtomicInteger are implemented like that.
The increment part is a completely different problem. Depending on what you mean by "increment a float", it either requires you to add one to the number, or increment it by one ULP. For the latter, in Java 6, the Math.nextUp method is what you are looking for. For decrement by one ULP, the Math.nextAfter method is useful.

Related

Java int cast to float cast to int does not equal original int

Using this snippet:
public static void main(String[] args){
int i = XXX;
System.out.println( (int) ( (float) i ) );
}
If int i = 1234; then the output is 1234
If int i = Integer.MAX_VALUE; then the output is equal to Integer.MAX_VALUE
However, if int i = 1234567990;, then the output is 1234567936, which is not equal to i.
And if int i = 1235567990;, then the output is 1235568000, which is also not equal to i.
How does this casting conversion math work?
This is entirely normal for floating point maths. Both int and float are 32-bit values. float only has about 7 significant digits of precision, because it uses some of the bits for scale. As you get to large values, "adjacent" float values (i.e. going from one precisely-representable value to the next one up) are more than 1 apart - so any integer between those two adjacent values can't be represented precisely as a float.
Another way of looking at this is a version of the pigeonhole principle:
Both float and int have 2^32 possible bit patterns
There's a valid mapping from every int to a float value
Every bit pattern is a valid int, so there are 2^32 possible integer values
float also contains the value 1.5 (and many other non-integers, but we only need one of them to prove the point)
Therefore at least two int values must map to the same float, which means the mapping cannot be reversible in every case
Note that if you use double, you're fine - every int can be cast to double and then cast back to int, and you'll get the original value. However, using double and long (instead of int) you get the same problem, for the same reason, but using 64 bits instead of 32.
How does this casting conversion math work?
Casting an int to a float works the same way any float operation works: Do the math (which in this case is nothing - just take the int as is), then convert it to the 'nearest representable float' - that float which is closer to the result of the calculation than any other.
Why is it 'lossy'? See the other answer.
What's the math behind which floats are representable? Wikipedia's page on IEEE754 floating point representation explains that.

Horner's recursive algorithm for fractional part - Java

I am trying to create a recursive method that uses Horner's algorithm to convert a fractional number in base n to base 10. I've searched here and all over but couldn't find anywhere that dealt with the fractional part in detail. As a heads up, I'm pretty weak in recursion as I have not formally learned it in my programming classes yet, but have been assigned it by another class.
I was able to make a method that handles the integer part of the number, just not the fractional part.
I feel like the method I've written is fairly close as it gets me to double the answer for my test figures (maybe because I'm testing base 2).
The first param passed is an int array filled with the coefficients. I'm not too concerned with the order of the coefficients as I'm making all the coefficients the same to test it out.
The second param is the base. The third param is initialized to the number of coefficients minus 1 which I also used for the integer part method. I tried using the number of coefficients, but that steps out of the array.
I tried dividing by the base one more time as that would give me the right answer, but it doesn't work if I do so in the base case return statement or at the end of the final return statement.
So, when I try to convert 0.1111 base 2 to base 10, my method returns 1.875 (double the correct answer of 0.9375).
Any hints would be appreciated!
//TL;DR
coef[0] = 1; coef[1] = 1; coef[2] = 1; coef[3] = 1;
base = 2; it = 3;
//results in 1.875 instead of the correct 0.9375
public static double fracHorner(int[] coef, int base, int it) {
if (it == 0) {
return coef[it];
}
return ((float)1/base * fracHorner(coef, base, it-1)) + coef[it];
}
Observe that fracHorner always returns a value at least equal to coef[it] because it either returns coef[it] or something positive added to coef[it]. Since coef[it] >= 1 in your tests, it will always return a number greater than or equal to one.
It's relatively easy to fix: divide both coef[it] by base:
public static double fracHorner(int[] coef, int base, int it) {
if (it == 0) {
return ((double)coef[it])/base;
}
return (fracHorner(coef, base, it-1) + coef[it])/base;
}

Why does Math.ceil return a double?

When I call Math.ceil(5.2) the return is the double 6.0. My natural inclination was to think that Math.ceil(double a) would return a long. From the documentation:
ceil(double a)
Returns the smallest (closest to negative infinity) double value
that is not less than the argument and is equal to a mathematical
integer.
But why return a double rather than a long when the result is an integer? I think understanding the reason behind it might help me understand Java a bit better. It also might help me figure out if I'll get myself into trouble by casting to a long, e.g. is
long b = (long)Math.ceil(a);
always what I think it should be? I fear there could be some boundary cases that are problematic.
The range of double is greater than that of long. For example:
double x = Long.MAX_VALUE;
x = x * 1000;
x = Math.ceil(x);
What would you expect the last line to do if Math.ceil returned long?
Note that at very large values (positive or negative) the numbers end up being distributed very sparsely - so the next integer greater than integer x won't be x + 1 if you see what I mean.
A double can be larger than Long.MAX_VALUE. If you call Math.ceil() on such a value you would expect to return the same value. However if it returned a long, the value would be incorrect.

How to alter a float by its smallest increment in Java?

I have a double value d and would like a way to nudge it very slightly larger (or smaller) to get a new value that will be as close as possible to the original but still strictly greater than (or less than) the original.
It doesn't have to be close down to the last bit—it's more important that whatever change I make is guaranteed to produce a different value and not round back to the original.
(This question has been asked and answered for C, C++)
The reason I need this, is that I'm mapping from Double to (something), and I may have multiple items with the save double 'value', but they all need to go individually into the map.
My current code (which does the job) looks like this:
private void putUniqueScoreIntoMap(TreeMap map, Double score,
A entry) {
int exponent = 15;
while (map.containsKey(score)) {
Double newScore = score;
while (newScore.equals(score) && exponent != 0) {
newScore = score + (1.0d / (10 * exponent));
exponent--;
}
if (exponent == 0) {
throw new IllegalArgumentException("Failed to find unique new double value");
}
score = newScore;
}
map.put(score, entry);
}
In Java 1.6 and later, the Math.nextAfter(double, double) method is the cleanest way to get the next double value after a given double value.
The second parameter is the direction that you want. Alternatively you can use Math.nextUp(double) (Java 1.6 and later) to get the next larger number and since Java 1.8 you can also use Math.nextDown(double) to get the next smaller number. These two methods are equivalent to using nextAfter with Positive or Negative infinity as the direction double.
Specifically, Math.nextAfter(score, Double.MAX_VALUE) will give you the answer in this case.
Use Double.doubleToRawLongBits and Double.longBitsToDouble:
double d = // your existing value;
long bits = Double.doubleToLongBits(d);
bits++;
d = Double.longBitsToDouble(bits);
The way IEEE-754 works, that will give you exactly the next viable double, i.e. the smallest amount greater than the existing value.
(Eventually it'll hit NaN and probably stay there, but it should work for sensible values.)
Have you considered using a data structure which would allow multiple values stored under the same key (e.g. a binary tree) instead of trying to hack the key value?
What about using Double.MIN_VALUE?
d += Double.MIN_VALUE
(or -= if you want to take away)
Use Double.MIN_VALUE.
The javadoc for it:
A constant holding the smallest positive nonzero value of type double, 2-1074. It is equal to the hexadecimal floating-point literal 0x0.0000000000001P-1022 and also equal to Double.longBitsToDouble(0x1L).

Checking if value of int[] can be long

I have an array of ints ie. [1,2,3,4,5] . Each row corresponds to decimal value, so 5 is 1's, 4 is 10's, 3 is 100's which gives value of 12345 that I calculate and store as long.
This is the function :
public long valueOf(int[]x) {
int multiplier = 1;
value = 0;
for (int i=x.length-1; i >=0; i--) {
value += x[i]*multiplier;
multiplier *= 10;
}
return value;
}
Now I would like to check if value of other int[] does not exceed long before I will calculate its value with valueOf(). How to check it ?
Should I use table.length or maybe convert it to String and send to
public Long(String s) ?
Or maybe just add exception to throw in the valueOf() function ?
I hope you know that this is a horrible way to store large integers: just use BigInteger.
But if you really want to check for exceeding some value, just make sure the length of the array is less than or equal to 19. Then you could compare each cell individually with the value in Long.MAX_VALUE. Or you could just use BigInteger.
Short answer: All longs fit in 18 digits. So if you know that there are no leading zeros, then just check x.length<=18. If you might have leading zeros, you'll have to loop through the array to count how many and adjust accordingly.
A flaw to this is that some 19-digit numbers are valid longs, namely those less than, I believe it comes to, 9223372036854775807. So if you wanted to be truly precise, you'd have to say length>19 is bad, length<19 is good, length==19 you'd have to check digit-by-digit. Depending on what you're up to, rejecting a subset of numbers that would really work might be acceptable.
As others have implied, the bigger question is: Why are you doing this? If this is some sort of data conversion where you're getting numbers as a string of digits from some external source and need to convert this to a long, cool. If you're trying to create a class to handle numbers bigger than will fit in a long, what you're doing is both inefficient and unnecessary. Inefficient because you could pack much more than one decimal digit into an int, and doing so would give all sorts of storage and performance improvements. Unnecessary because BigInteger already does this. Why not just use BigInteger?
Of course if it's a homework problem, that's a different story.
Are you guaranteed that every value of x will be nonnegative?
If so, you could do this:
public long valueOf(int[]x) {
int multiplier = 1;
long value = 0; // Note that you need the type here, which you did not have
for (int i=x.length-1; i >=0; i--) {
next_val = x[i]*multiplier;
if (Long.MAX_LONG - next_val < value) {
// Error-handling code here, however you
// want to handle this case.
} else {
value += next_val
}
multiplier *= 10;
}
return value;
}
Of course, BigInteger would make this much simpler. But I don't know what your problem specs are.

Categories

Resources