5

I don't understand how floating point numbers are represented in hex notation in Swift. Apple's documentation shows that 0xC.3p0 is equal to 12.1875 in decimal. Can someone walk me through how to do that conversion? I understand that before the decimal hex value 0xC = 12. The 3p0 after the decimal is where I am stumped.

5 Answers5

12

From the documentation:

Floating-Point Literals
...
Hexadecimal floating-point literals consist of a 0x prefix, followed by an optional hexadecimal fraction, followed by a hexadecimal exponent. The hexadecimal fraction consists of a decimal point followed by a sequence of hexadecimal digits. The exponent consists of an upper- or lowercase p prefix followed by a sequence of decimal digits that indicates what power of 2 the value preceding the p is multiplied by. For example, 0xFp2 represents 15 × 22, which evaluates to 60. Similarly, 0xFp-2 represents 15 × 2-2, which evaluates to 3.75.

In your case

  0xC.3p0 = (12 + 3/16) * 2^0 = 12.1875

Another example:

  0xAB.CDp4 = (10*16 + 11 + 12/16 + 13/16^2) * 2^4 = 2748.8125

This format is very similar to the %a printf-format (see for example http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html). It can be used to specify a floating point number directly in its binary IEEE 754 representation, see Why does Swift use base 2 for the exponent of hexadecimal floating point values? for more information.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Nice answer. The great thing about hex literals for floating point numbers us that they're always exact, whereas many decimal values can't be represented exactly in floating point. Also, if you get a translator be sure it speaks Bocce. – rickster Apr 20 '15 at 03:04
  • Also notice the star wars reference if you want to become a true geek :) – Demircan Celebi Oct 04 '15 at 12:31
  • @Martin, your another example has a mistake - 0xC is 12 not 13 and 0xD is 13 ;) End result is correct, though. – matm Sep 20 '17 at 06:58
5

Interpret 0xC.3p0 using the place value system:

C (or 12) is in the 16^0 place
3 is in the 16^-1 place (and 3/16 == 0.1875)
p says the exponent follows (like the e in 6.022e23 in base 10)
0 is the exponent (in base 10) that is the power of 2 (2^0 == 1)

So putting it all together

0xC.3p0 = (12 + (3/16)) * 2^0 = 12.1875
vacawama
  • 150,663
  • 30
  • 266
  • 294
  • The documentation looks to be contractory to me. First it says "Hexadecimal floating-point literals consist of a 0x prefix, followed by an optional hexadecimal fraction, followed by a **hexadecimal** exponent." Then it says "The exponent consists of an upper- or lowercase p prefix followed by a sequence of decimal digits..." This sounds like an editing error in the docs. My guess is the exponent is in base 16 like the rest of the expression. – Duncan C Apr 19 '15 at 21:17
  • 1
    Testing shows that the exponent is in base 10 but it represents a power of 2. So `p10` represents `2^10` and not 2^`16`. – vacawama Apr 19 '15 at 21:23
  • Why in the world does Swift hex floating point notation take an exponent that's a power of 2? In decimal, scientific notation takes a power of 10, which shifts the value up or down by a certain number of decimal digits. It would make much more sense to me if the exponent was in hex as well. Then it would shift the value up or down by a certain number of hex digits. Clear and consistent. – Duncan C Aug 12 '15 at 20:31
1

In order to sum up what I've read, you can see those representations as follow:

0xC.3p0 = (12*16^0 + 3*16^-1) * 2^0 = 12.1875

From Martin R's example above :

0xAB.CDp4 = (10*16^1 + 11*16^0 + 12*16^-1 + 13*16^-2) * 2^4 = 2748.8125
Mat P
  • 11
  • 1
0

The 0xC is 12, as you said. The decimal part is ((1/16)*3)*10^0.

So you need to take the decimal part and divide it by 16. Then you need to multiply it by 2 raised to the power of the number after the p

user2340612
  • 10,053
  • 4
  • 41
  • 66
0

Hexadecimal -(0-9,A=10,B=11,C=12,D=13,E=14,F=15) and p0 means 2^0 ex: - 0xC = 12 (0x prefix represents hexadecimal) After the decimal part as in 0xC.3p0 we divide the numbers with the power of 16

So here its 3/16 = 0.1875 so 0xC.3p0 = (12 + (3/16) ) 2^0

If it was 0xC.43p0 then for the 4 we would use 4/(16), for 3 we would use 3/(16 ^2) and similarly if the decimal part increases.

ex: 0xC.231p1 = (12 + 2/16 + 3/(256) + 1/(16^3)) 2^1 = 24.27392578125

Tim Ogilvy
  • 1,923
  • 1
  • 24
  • 36
Raushan
  • 1
  • 2