【问题标题】:Specify a specific double precision literal in c#在 c# 中指定特定的双精度文字
【发布时间】:2014-06-26 08:38:26
【问题描述】:

如何在 c# 中指定特定的 double 精度文字或值?

例如,我想在程序中使用小于 1 的最大 double 值的常量。小于一的最大double 是二进制的1.11111111 11111111 11111111 11111111 11111111 11111111 1111 x 2^(-1)。将其表示为十六进制的 big-endian double 将是 0x3fe f ffff ffff ffff

我可以使用以下代码生成它:

var largestDoubleLessThanOneBytes = new byte[] {0x3f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
if (BitConverter.IsLittleEndian) largestDoubleLessThanOneBytes = largestDoubleLessThanOneBytes.Reverse().ToArray();
double largestDoubleLessThanOne = BitConverter.ToDouble(largestDoubleLessThanOneBytes, 0);

BitConverter 不能用于 const 的声明中,因此不能用于代替文字值。

使用this tool,我可以得到文字9.99999999999999888977697537484E-1,它最终是完全相同的双精度数。 BitConverter.ToString(BitConverter.GetBytes(9.99999999999999888977697537484E-1)) == "FF-FF-FF-FF-FF-FF-EF-3F".

除了找到一个十进制文字,其最接近的双精度表示是您想要的双精度,还有其他方法可以将特定的double 值放入 c# 代码中吗?

【问题讨论】:

  • 您还可以使用 c# 代码使用 .ToString("R") 为双精度数吐出适当的十进制文字。在这种情况下,它将是0.99999999999999989。尝试在字符串格式中添加足够的小数位以输出足够精确的值以用作文字是行不通的,为什么请参阅stackoverflow.com/questions/1421520/…
  • 在 Java 中,我会使用 Math.nextAfter(1.0, Double.NEGATIVE_INFINITY)。这可能是 C# nextAfter 函数的情况吗?

标签: c# double


【解决方案1】:

这可能有点矫枉过正,但该死的,为什么不呢?

unsafe
{
    var x = 0x3fefffffffffffff;
    var d = *(double*)&x;
    Console.WriteLine("{0:r}", d);
}

你好,C# 中的reinterpret_cast<>

【讨论】:

  • 不幸的是,.Net 4.5 C# 编译器不够聪明,无法优化掉*&,更不用说*(double*)&。它会产生ldc.i8stloclsloca.sconf.uldind.r8stloc 并使用两个本地而不是简单地使用单个本地 ldc.r8stloc
  • .Net 代码中真正的优化是在 JIT 编译期间进行的。我不知道 JITter 有多聪明,但它可能在这里发挥重要作用。无论如何,既然你想指定一个编译时常量,它应该没什么关系。
猜你喜欢
  • 2023-03-29
  • 1970-01-01
  • 2019-05-22
  • 2020-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多