【问题标题】:Can i store a UInt32, Int32 and a float value inside a double without losing information?我可以在双精度内存储 UInt32、Int32 和浮点值而不会丢失信息吗?
【发布时间】:2015-03-14 18:15:41
【问题描述】:

我需要将 UInt32、Int32 和浮点值保存在一个变量中。我可以使用double 而不丢失信息(例如在转换中丢失一些数字)还是需要使用任意精度类?

从我目前的研究看来我可以,因为我可以存储 UInt32 的最大值而不会丢失信息:

Assert.AreEqual(UInt32.MaxValue, Convert.ToUInt32(Convert.ToDouble(UInt32.MaxValue)));
  • 因此 double 应该支持足够的数字来表示所有小于或等于 UInt32.MaxValue 的数字。
  • 无论如何,Int32 的取值范围较小,因此也受支持。
  • 也应该支持浮点数,因为它只是精度较低的两倍。

有什么我错过的吗?

【问题讨论】:

  • 好吧,您可以将它们存储在 Decimal 中:“这种类型提供了将 Decimal 值与 SByte、Int16、Int32、Int64、Byte、UInt16、UInt32 和 UInt64 值相互转换的方法。从这些整数类型到 Decimal 的转换正在扩大转换范围,不会丢失信息或引发异常。”

标签: c# double type-conversion precision ieee-754


【解决方案1】:

能够在不丢失信息的情况下存储UInt32 的最大值并不一定意味着您能够在不丢失信息的情况下将所有值存储在UInt32 - 毕竟,有很多 long可以 存储在 double 中,即使一些较小的值不能。 (例如,262 可以很容易地准确存储在 double 中,但 262 - 1 则不能。)

但是,您好的 - the mantissa for double is 52-bits long,因此任何少于 52 位的整数都可以简单地存储为 value * 20(即有效比例0).

是的,float 值也可以转换为 double 而不会损失精度。

但是,请注意,这并不意味着例如 0.1f == 0.1d - 它只是意味着 (double) 0.1f0.1f 完全相同,但表示形式不同。

还值得注意的是,Int32 的范围并不比 UInt32 更小 - 它们的范围都正好是 232 个连续值。但是,Int32 确实 具有较小的“绝对”值,并且与符号以浮点值表示的方式有关,这是相关的。您实际上仍然需要 32 位来存储每个 Int32 的绝对值,因为 Int32.MinValue 在二进制中是 -10000...0000(总共 32 位),或者 -(231 + 1)。

最后,float 不仅仅是精度较低的 double - 它的范围也更小。与double 中的 11 位相比,它的指数只有 8 位。因此,double 范围内的数字超出了float 的范围,即使它们没有很多有效(二进制)数字。

【讨论】:

  • "任何小于 52 位的整数都可以简单地存储为 value * 2^0" 这部分答案有点误导,因为尾数部分不存储整数,而是存储之间的二进制小数1 和 2。当用浮点数表示整数时,您确实需要使用非零指数才能将点移动到正确的位置。
  • @JoanCharmant:将整数或二进制小数视为一个整数或二进制分数仅仅是关于它移动多远的不同观点的问题。我发现将其视为整数更简单。 YMMV。我当然认为将具有整数结果的值视为按 0 缩放的整数比按二进制分数缩放的值更简单……这就是为什么我将其称为 有效 比例。指数的位模式的详细信息以及归一化在此处不相关,除非计算出整数不再能够精确表示的 精确 点。
猜你喜欢
  • 1970-01-01
  • 2011-08-24
  • 1970-01-01
  • 1970-01-01
  • 2014-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多