【问题标题】:toString(16) with a decimal pointtoString(16) 带小数点
【发布时间】:2013-09-30 19:47:38
【问题描述】:

我理解二进制,但我不理解十六进制。

这里有一些例子:

Number(0.15).toString(16) // 0.26666666666666
Number(1.5).toString(16) // 1.8
Number(.18).toString(16) // 0.2e147ae147ae14

看起来十进制在转换为十六进制时增加了大约 40%,当你从 10 到 16 时这真的没有意义。它应该像整数一样下降,对吧?

如果正确/不正确:您如何手动执行此操作?我完全理解转换整数,但是当 dec 值为小数时,我还没有找到将 dec 转换为十六进制的来源。

【问题讨论】:

  • 您所看到的是二进制数的十六进制表示 - 这通常是“与数字中的位数一样多”。大多数小数不能完全表示为二进制数。因此,您会看到“尽可能多地显示”。如果您以十进制打印数字0.18,您会看到它一直在继续。
  • @Floris 我不确定这是否是完整的解释。这不像价值观是“一点点”。相反,“看起来小数转换为十六进制时增加了大约 40%”.. 那么 非整数转换的规则是什么?
  • @Floris 所以它本质上是转换为二进制,然后采用 4 组并直接转换为十六进制,对吗? 3.625 = 11.101 二进制,但由于这只是小数点后的一组 3,因此将其更改为 11.1010,进而变为十六进制的 3.A。这就是它的工作方式,但这实际上在数学上是正确的吗?我认为十六进制不应该高于十进制。
  • 是的,这是正确的。 DesertIvy 的回答很好地解释了这一点。

标签: javascript tostring


【解决方案1】:

首先,不要将小数视为“增加约 40%”。数字是相等的 - 它们只是使用不同的数字系统表示。

让我们看看将十进制数转换为二进制,然后再转换为十六进制时发生了什么。至少对我来说,这使它更容易理解:

取十进制数0.15:二进制是0.0010 0110 0110 0110 0110 0110 0110 0110...。 (为清楚起见添加了空格。)注意到任何有趣的事情吗?如果将这些四位块中的每一个块转换为十六进制等效项,您将得到 toString(16) 调用给您的确切内容:0.2666666...(二进制中的0010 = 十六进制中的2)。

为什么会这样?因为在小数点之后,您可以将每个条目视为 2 的反幂。意思是小数点后每一位代表:

 .1 |  .01 |  .001 |  .0001 |  .00001... (BIN)
0.5 | 0.25 | 0.125 | 0.0625 | 0.03125... (DEC)

那么我们如何在二进制中表示1.5?好吧,小数点前的一切都应该很容易(只是1),但在那之后,我们只需停在1.1(二进制),因为1 + 0.5(十进制)=1.5(十进制)=1.1000 (二进制)。

我在其中添加了一些额外的零,以使下一次转换更容易,因为接下来我们将这四位块转换为十六进制,即1.8

【讨论】:

  • 我不明白为什么零放在右边而不是左边?例如。 3.625 = 11.101,因为小数点后没有 4 位数字,所以在右边添加了一个零,即 11.1010。这将转换为 3.A。 A 高于 6,这会使十进制的 3.625 看起来比十六进制的 3.A 小。如果将零添加到左侧会更有意义,创建 11.0101 或 3.5。 3.5 低于 3.625,适合更高的基数。我知道你没有错,但它似乎倒退了。
  • 好吧,二进制的11.0101 不是十进制的3.5。实际上是2 + 1 + .25 + .0625 = 3.3125。零放在左边,因为这就是数字的书写方式,无论其基数如何。这样想:我可以在任何数字的右侧添加任意数量的0s,因为它不会改变值:3.14 = 3.140000... 但是如果我开始向 right 添加零在我的数字中,发生了不好的事情:3.14 != 3.014。不同基数的系统工作方式完全相同,但我们只是在“携带”时改变。
  • 小数后与左边的数字分开处理。例如。它似乎相当于将 14 与 014 进行比较,而不是将 0.14 与 0.014 进行比较。谢谢你的回答。
  • 我想最好的看待它的方式是十进制数的 0-9 被延伸到十六进制数的 0-F 的频谱。由于小数的逆性质,这会导致十六进制小数大于十进制小数。
  • 听起来你已经明白了。 :)
【解决方案2】:

我以前从未想过的有趣问题,但经过一些研究,完全有道理。

如果您想用十六进制表示十进制值24,您可以像这样将该值除以 16:24/16 = 1,余数 8 ---> 所以十六进制中的“16”位是 1 和“1”的数字是 8,最终的十六进制值是 18

十进制数的“小数”部分经历了一种类似的过程,但不是除以 16,而是乘以 16。因此,使用您的示例,您可以逐步完成该过程:

十进制数0.15 = 十六进制数0.26666666666666

  • .15 * 16 = 2.4 ---> 十六进制值 0.2(保留 2,继续 .4)
  • .4 * 16 = 6.4 ---> 十六进制值 0.26(保留 6,继续 .4)
  • .4 * 16 = 6.4 ---> 十六进制值 0.266(保留 6,继续 .4)
  • .4 * 16 = 6.4 ---> 十六进制值 0.2666(保留 6,继续 .4)
  • 。 . . .

十进制数1.5 = 十六进制数1.8

  • 1.5 ---> 十六进制值 1(保留 1,继续 .5)
  • .5 * 16 = 8 ---> 十六进制值1.8

十进制数.18 = 十六进制数0.2e147ae147ae14

  • .18 * 16 = 2.88 ---> 十六进制值 0.2(保留 2,继续 .88)
  • .88 * 16 = 14.08 ---> 十六进制值 0.2e(保留 14 [或“e”],继续 .8)
  • .08 * 16 = 1.28 ---> 十六进制值 0.2e1(保留 1,继续 .28)
  • .28 * 16 = 4.48 ---> 十六进制值 0.2e14(保留 4,结转 0.48)
  • 。 . . .

一旦你稍微了解一下,它实际上很有意义,但它肯定不是第一眼就能清楚地呈现出来的东西。 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-30
    • 2011-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多