【每天学一点】一个浮点数的疑问(2021.2.2)

1,044 阅读2分钟

参考:swiftgg.gitbook.io/swift/swift…

今天闲来想着翻翻《Swift Programming Guide》,看到一个十进制数12.1875的十六进制表示, 思考了一会才想出答案。

let hexadecimalDouble = 0xC.3p0  // 十进制的12.1875

原文内容如下:

-------原文开始------

浮点字面量可以是十进制(没有前缀)或者是十六进制(前缀是 0x )。小数点两边必须有至少一个十进制数字(或者是十六进制的数字)。十进制浮点数也可以有一个可选的指数(exponent),通过大写或者小写的 e 来指定;十六进制浮点数必须有一个指数,通过大写或者小写的 p 来指定。

如果一个十进制数的指数为 exp,那这个数相当于基数和10^exp 的乘积:

  • 1.25e2 表示 1.25 × 10^2,等于 125.0。
  • 1.25e-2 表示 1.25 × 10^-2,等于 0.0125。

如果一个十六进制数的指数为 exp,那这个数相当于基数和2^exp 的乘积:

  • 0xFp2 表示 15 × 2^2,等于 60.0。
  • 0xFp-2 表示 15 × 2^-2,等于 3.75。 下面的这些浮点字面量都等于十进制的 12.1875:
let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0    // <<<< 这是问题

-------原文结束------

答案

问题的根结在于思维停滞在了10进制上,但是又没有延伸到十六进制

// 对于十进制的12.1875, 对应十进制表示为
1 * 10^1 + 2 * 10^0 + 1 * 10^-1 + 8 * 10^-2 + 7 * 10^-3 + 5 * 10^-4 

// 同理对于十六进制的0xC.3p0,对应的表示为
(12 * 16 ^ 0 + 3 * 16 ^ -1) * 2^0 == 12 + 3 / 16 == 12.1875

同样的道理(将过程公式化)也适合求余数

// 针对正数的求余数
10 % 3 == (3 * 最大倍数) + 余数 == 3 * 3 + 余数
得结果: 余数 = 1;

// 针对负数的求余数
-10 % 3 = (3 * 最大倍数) + 余数 == 3 * -3 + 余数
得结果:余数 = -1;