/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
{
// your code goes here
// }
// https://stackoverflow.com/questions/44008357/adding-and-subtracting-exact-values-to-float
//public class Toy {
// public static void main(String args[]) {
int length = 0x82000000;
int x = length >>> 24;
int y = (length >>> 24) & 0xFF;
System.
out.
println("length = " + length
+ ", x = " + x
+ ", y = " + y
);
float float0 = 1.5f;
float float1 = 1.5000001f;
float float2 = 1.5000002f;
float float4 = 1.5000004f;
float float5 = 1.5000005f;
// testLeaps(float0, float4);
// testLeaps(0, float5);
// testLeaps(0, -float1);
// testLeaps(-float1, 0);
System.
out.
println(INT_POWER_MASK
& Float.
floatToIntBits(-float0
)); System.
out.
println(INT_POWER_MASK
& Float.
floatToIntBits(float0
)); // testLeaps(-float1, -float0);
testLeaps(-float0, 0);
testLeaps(float0, 0);
}
public static void testLeaps(float value, float destination) {
System.
out.
println("optLeaps(" + value
+ ", " + destination
+ ") = " + optLeaps
(value, destination
)); System.
out.
println("getLeaps(" + value
+ ", " + destination
+ ") = " + getLeaps
(value, destination
)); }
public static final int INT_POWER_MASK = 0x7f800000 | 0x007fffff; // ~0x80000000
/**
* Retrieves the integer difference between two float-point values according to
* the IEEE 754 floating-point "single format" bit layout.
*
* <pre>
* mask 0x80000000 | 0x7f800000 | 0x007fffff
* sign | exponent (8 bits) | coefficient/significand/mantissa/fraction (23 bits)
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | | | |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* 31 30 23 22 0
* 0x7fc00000 => NaN
* 0x7f800000 +Infinity
* 0xff800000 -Infinity
* </pre>
*
* Using base (radix) 10, the numerical value of such a float type number is
* `(-1)^sign x coefficient x 10^exponent`, so the coefficient is a key factor
* to calculation of leaps coefficient.
*
* @param value the first operand
* @param destination the second operand
* @return the integer span from {@code value} to {@code destination}
* @see <a href="https://e...content-available-to-author-only...a.org/wiki/Single-precision_floating-point_format">sign.exponent.mantissa</a>
*/
public static int optLeaps(float value, float destination) {
// TODO process possible cases for some special inputs.
int valueBits
= Float.
floatToIntBits(value
); // IEEE 754 floating-point "single format" bit layout int destinationBits
= Float.
floatToIntBits(destination
); // IEEE 754 floating-point "single format" bit layout int leaps; // Float.intBitsToFloat();
if ((destinationBits ^ valueBits) >= 0) {
leaps
= Math.
abs(destinationBits
- valueBits
); } else {
leaps = (INT_POWER_MASK & destinationBits) + (INT_POWER_MASK & valueBits);
}
return leaps;
}
public static int getLeaps(float value, float destination) {
int leaps = 0;
float signum
= Math.
signum(destination
- value
);
// float direction = Float.POSITIVE_INFINITY * signum;
// while (value * signum < destination * signum) {
// value = Math.nextAfter(value, direction); // Float.POSITIVE_INFINITY * direction
// leaps++;
// }
if (0 == signum) {
return 0;
}
if (0 < signum) {
while (value < destination) {
value
= Math.
nextAfter(value,
Float.
POSITIVE_INFINITY); leaps++;
}
} else {
while (value > destination) {
value
= Math.
nextAfter(value,
Float.
NEGATIVE_INFINITY); leaps++;
}
}
return leaps;
}
// may optimiaze to reduce the elapsed time by roughly half
//}
}