Being Creative with Numeric Literals in Java 2015-01-30

Did you know that 0X0.P0D is just an odd way of writing 0.0 in Java (and C)? Or that 0x.1921_FB_C0P5 is a rough approximation of Pi? On the surface the specification of floating-point literals in Java seems simple, but you can write some really confusing stuff that still parses correctly. Let’s look at some simple floating-point literals to start:

1.1
1.
 .1

These are valid floating-point literals, and they are easy to read. Things get more interesting when you add in the optional exponent part:

1.0e2  (= 100.0)
  1e-2 (= 0.01)
 1.e2  (= 100.0)
 .1e2  (= 10.0)

The first two examples are easily recognizable as numbers, but the third and fourth examples are a little more difficult to read. I think the third example could easily be misread as I.e2 which has an entirely different meaning. Things get even harder to read if you add a precision specifier (F or D):

.1e0d (= 0.1, double)
5.E0F (= 5.0, float)

The 5.E0F literal looks a bit like S.EOF.

Let us get even more crazy with hexadecimal floating-point literals! These look like an ordinary hexadecimal number but can contain a decimal point and must end with an exponent part where P replaces E as exponent prefix character, and the exponent uses powers of two:

0x1P2 (= 4.0)
0x1P4 (= 16.0)
0xC3P0
0xCAFE.P00

There are lots of word-like strings that can be formed in a hexadecimal floating-point literal. For example

0xA.P00F
0xB00P-0F
0xBAD.P0D
0xC0P5
0xCAP5
0x00P5
0xDEAD.BEEP5

These word-like strings work best if your typeface has zeroes without slash or dot, so that they are more similar to Os. The 00P5 (OOPS) suffix can be put at the end of anything. You just have to divide the number you want by 32, and write it in hexadecimal floating-point notation and append 00P5. Here is Pi with the 00P5 suffix:

0x.1921FB54442D1100P5   (Java 6)
0x.1921FB54442D11__00P5 (Java 7+)

Java 7 added underscores in numeric literals, so you can make the OOPS more noticeable with an underscore or two!

If you want to make your floating point literals really unreadable you can add a sign to the exponent and surround the literal with addition or subtraction expressions. Here are some examples:

0xf.P+8D
-1.e+7d+1.-1e-7d
-.0e-0_0f  (Java 7+)

One final example of perfectly legal Java code:

class E {
  double e;
  double e(E e5) {
    double d5e = .8-0- -0-8.; // palindrome expression!
    return .5e-5f-5.e+5d-d5e+e5.e;
  }
}

Compiler Bugs!

I tried out some of these floating point literals in Eclipse and incidentally found a bug: Eclipse accepted 0XP00 as a valid literal, however it is actually invalid because it does not have any digits in it! I reported this bug to the Eclipse developers and they seem to have made a patch for the issue already!

Categories: Uncategorized

Leave a Reply

Your email address will not be published. Required fields are marked *