[英]Extracting mantissa and exponent from double in c#
Is there any straightforward way to get the mantissa and exponent from a double in c# (or .NET in general)?有什么直接的方法可以从 c#(或一般的 .NET)中的双精度数中获取尾数和指数?
I found this example using Google, but I'm not sure how robust it would be.我使用 Google 找到了这个示例,但我不确定它的可靠性如何。 Could the binary representation for a double change in some future version of the framework, etc?是否可以在某些未来版本的框架等中进行双重更改的二进制表示?
The other alternative I found was to use System.Decimal instead of double and use the Decimal.GetBits() method to extract them.我发现的另一种选择是使用 System.Decimal 而不是 double 并使用Decimal.GetBits()方法来提取它们。
Any suggestions?有什么建议么?
The binary format shouldn't change - it would certainly be a breaking change to existing specifications.二进制格式不应该改变——这肯定是对现有规范的重大改变。 It's defined to be in IEEE754 / IEC 60559:1989 format, as Jimmy said.正如吉米所说,它被定义为 IEEE754 / IEC 60559:1989 格式。 (C# 3.0 language spec section 1.3; ECMA 335 section 8.2.2). (C# 3.0 语言规范第 1.3 节;ECMA 335 第 8.2.2 节)。 The code in DoubleConverter should be fine and robust. DoubleConverter 中的代码应该很好而且很健壮。
For the sake of future reference, the relevant bit of the code in the example is:为了将来参考,示例中代码的相关位是:
public static string ToExactString (double d)
{
…
// Translate the double into sign, exponent and mantissa.
long bits = BitConverter.DoubleToInt64Bits(d);
// Note that the shift is sign-extended, hence the test against -1 not 1
bool negative = (bits & (1L << 63)) != 0;
int exponent = (int) ((bits >> 52) & 0x7ffL);
long mantissa = bits & 0xfffffffffffffL;
// Subnormal numbers; exponent is effectively one higher,
// but there's no extra normalisation bit in the mantissa
if (exponent==0)
{
exponent++;
}
// Normal numbers; leave exponent as it is but add extra
// bit to the front of the mantissa
else
{
mantissa = mantissa | (1L << 52);
}
// Bias the exponent. It's actually biased by 1023, but we're
// treating the mantissa as m.0 rather than 0.m, so we need
// to subtract another 52 from it.
exponent -= 1075;
if (mantissa == 0)
{
return negative ? "-0" : "0";
}
/* Normalize */
while((mantissa & 1) == 0)
{ /* i.e., Mantissa is even */
mantissa >>= 1;
exponent++;
}
…
}
The comments made sense to me at the time, but I'm sure I'd have to think for a while about them now.这些评论当时对我来说很有意义,但我相信我现在必须考虑一段时间。 After the very first part you've got the "raw" exponent and mantissa - the rest of the code just helps to treat them in a simpler fashion.在第一部分之后,您已经获得了“原始”指数和尾数 - 其余代码只是帮助以更简单的方式处理它们。
The representation is a IEEE standard and shouldn't change.该表示是 IEEE 标准,不应更改。
https://msdn.microsoft.com/en-us/library/system.double(v=vs.110).aspxhttps://msdn.microsoft.com/en-us/library/system.double(v=vs.110).aspx
The Double type complies with the IEC 60559:1989 (IEEE 754) standard for binary floating-point arithmetic. Double 类型符合 IEC 60559:1989 (IEEE 754) 二进制浮点运算标准。
EDIT: The reason why decimal has a getBits and double does not is that decimal preserves significant digits.编辑:decimal 有 getBits 而double 没有的原因是decimal 保留了有效数字。 3.0000m == 3.00m but the exponents/mantissas are actually different. 3.0000m == 3.00m 但指数/尾数实际上是不同的。 I think floats/doubles are uniquely represented.我认为浮动/双打是唯一代表。
I can think of another way by using double.ToString("E17")
and parsing the resulting scientific notation string.我可以通过使用double.ToString("E17")
并解析生成的科学记数法字符串来想到另一种方法。 But this method will be inaccurate for the mantissa extraction if the double has too many significant digits.但是如果双精度数的有效数字太多,这种方法对于尾数提取将不准确。
public class DoubleParser
{
public static int GetExponent(double d)
{
var doubleParts = ExtractScientificNotationParts(d);
return Convert.ToInt32(doubleParts[1]);
}
public static double GetMantissa(double d)
{
var doubleParts = ExtractScientificNotationParts(d);
return Convert.ToDouble(doubleParts[0]);
}
private static string[] ExtractScientificNotationParts(double d)
{
var doubleParts = d.ToString(@"E17").Split('E');
if (doubleParts.Length != 2)
throw new ArgumentException();
return doubleParts;
}
}
Use the class above like so:像这样使用上面的类:
var value1 = 43948530544.3433;
var mantissa = DoubleParser.GetMantissa(value1); // 4.39485305443433
var exponent = DoubleParser.GetExponent(value1); // 10
var value2 = 0.00000000009869232667160136;
mantissa = DoubleParser.GetMantissa(value2); // 9.8692326671601371
exponent = DoubleParser.GetExponent(value2); // -11
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.