Created
October 3, 2023 16:03
-
-
Save stanio/8e31e9f8a4641e87d22ca308ad597c93 to your computer and use it in GitHub Desktop.
Debugging float bits
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//package ; | |
import java.math.BigDecimal; | |
import java.util.Locale; | |
public class FloatTest { | |
// FloatConsts.SIGNIFICAND_WIDTH - 1 | |
static final int SIGNIF_SIZE = 23; | |
static final int EXP_SIZE = 8; | |
static final int EXP_MASK = 0xFF << SIGNIF_SIZE; | |
public static void main(String[] args) throws Exception { | |
float[] nums = { Float.POSITIVE_INFINITY, | |
Float.NEGATIVE_INFINITY, | |
Float.NaN, | |
0f, | |
-0f, | |
3.5f, | |
-3.25f, | |
3.125f, | |
Float.MIN_VALUE, | |
Float.MIN_NORMAL, | |
Float.MAX_VALUE }; | |
for (float n : nums) debugFloat(n); | |
System.out.println(); | |
System.out.println("*** Some exact binary == decimal floats:"); | |
final int seven = 0b0_10000001_11000000000000000000000; | |
debugFloat(Float.intBitsToFloat(seven)); | |
// 2 (+1 implied) bits for the integral | |
// 7 value: 11xxxxxxxxxxxxxxxxxxxxx | |
final int integSize = 2; | |
for (int b = 1; b < 16; b += 1) { | |
int fractionBits = Integer | |
.reverse(b) >>> (Float.SIZE - SIGNIF_SIZE + integSize); | |
debugFloat(Float | |
.intBitsToFloat(seven | fractionBits)); | |
} | |
System.out.println(); | |
System.out.println("---"); | |
debugFloat(Float.intBitsToFloat(0b0_01101010_00000000000000000000000)); | |
debugFloat(Float.intBitsToFloat(0b0_01101001_00000000000000000000000)); | |
debugFloat(Float.intBitsToFloat(0b0_01101000_00000000000000000000000)); | |
debugFloat(Float.intBitsToFloat(0b0_01100111_00000000000000000000000)); | |
debugFloat(Float.intBitsToFloat(0b0_01010010_00000000000000000000000)); | |
debugFloat(Float.intBitsToFloat(0b0_01010001_00000000000000000000000)); | |
debugFloat(Float.intBitsToFloat(0b0_01010000_00000000000000000000000)); | |
debugFloat(Float.intBitsToFloat(0b0_01001111_00000000000000000000000)); | |
System.out.println("---"); | |
debugFloat(0.3f); | |
debugFloat(0.4f); | |
debugFloat(0.5f); | |
debugFloat(0.7f); | |
debugFloat(0.3f + 0.4f); | |
System.out.println("---"); | |
debugFloat(Float.intBitsToFloat(0b0_01111110_11111111111111111111000)); | |
debugFloat(Float.intBitsToFloat(0b0_01111110_11111111111111111111100)); | |
debugFloat(Float.intBitsToFloat(0b0_01111110_11111111111111111111110)); | |
debugFloat(Float.intBitsToFloat(0b0_01111110_11111111111111111111111)); | |
debugFloat(1f); | |
debugFloat(Float.intBitsToFloat(0b0_01111111_00000000000000000000001)); | |
debugFloat(Float.intBitsToFloat(0b0_01111111_00000000000000000000010)); | |
debugFloat(Float.intBitsToFloat(0b0_01111111_00000000000000000000011)); | |
debugFloat(Float.intBitsToFloat(0b0_01111111_00000000000000000000100)); | |
debugFloat(Float.intBitsToFloat(0b0_01111111_00000000000000000000101)); | |
debugFloat(Float.intBitsToFloat(0b0_01111111_00000000000000000000110)); | |
debugFloat(Float.intBitsToFloat(0b0_01111111_00000000000000000000111)); | |
System.out.println("---"); | |
debugFloat(Float.intBitsToFloat(0b0_01111111_00000000000000000000001)); | |
debugFloat(Float.intBitsToFloat(0b0_10000000_00000000000000000000001)); | |
debugFloat(Float.intBitsToFloat(0b0_10000001_00000000000000000000001)); | |
debugFloat(Float.intBitsToFloat(0b0_10000010_00000000000000000000001)); | |
debugFloat(Float.intBitsToFloat(0b0_10000011_00000000000000000000001)); | |
debugFloat(Float.intBitsToFloat(0b0_10000100_00000000000000000000001)); | |
debugFloat(Float.intBitsToFloat(0b0_10000101_00000000000000000000001)); | |
debugFloat(Float.intBitsToFloat(0b0_10000110_00000000000000000000001)); | |
debugFloat(Float.intBitsToFloat(0b0_10000111_00000000000000000000001)); | |
System.out.println("---"); | |
debugFloat(Float.MAX_VALUE); | |
debugFloat(Float.MAX_VALUE - 1_234_567f); | |
float bigFloat = BigDecimal.valueOf(Float.MAX_VALUE / 2).floatValue(); | |
debugFloat(bigFloat); | |
System.out.append(floatString(bigFloat)) | |
.append(" + ").print(1_234_567f); | |
System.out.append(" =? ").append(floatString(bigFloat)) | |
.append(" (").print(bigFloat + 1_234_567f == bigFloat); | |
System.out.println("! 🤪)"); | |
} | |
static void debugFloat(float num) { | |
int floatBits = Float.floatToRawIntBits(num); | |
char sign = (floatBits < 0) ? '-' : ' '; | |
int exp = Math.getExponent(num); | |
String binStr = binaryString(floatBits); | |
String expBits = binStr.substring(1, 1 + EXP_SIZE); | |
String significand = binStr.substring(1 + EXP_SIZE); | |
char impliedBit = exp >= Float.MIN_EXPONENT | |
? (Float.isFinite(num) ? '1' : '*') | |
: '0'; | |
String decimal = Float.isFinite(num) | |
&& Math.abs(exp) / 2 < 40 | |
? new BigDecimal(Float.toString(num)).toPlainString() | |
: floatString(num); | |
System.out.printf(Locale.ROOT, "Bin: %s(%s).%sE%+d[%s], Dec: %s%n", | |
sign, impliedBit, significand, exp, expBits, decimal); | |
} | |
static String floatString(float num) { | |
return Float.toString(num).replaceFirst("E(\\d)", "E+$1"); | |
} | |
static String binaryString(int num) { | |
return String.format("%32s", Integer.toBinaryString(num)) | |
.replace(' ', '0'); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment