C# Math.Pow(等等)实际上是如何工作的

C# Math.Pow(等等)实际上是如何工作的,c#,.net,algorithm,disassembly,pow,C#,.net,Algorithm,Disassembly,Pow,所以我在谷歌上搜索了很长时间,几乎什么也没找到。我从中找到了一些关于Math.Pow可能实现的信息,但这些信息不准确,例如这段代码 public static double PowerA(double a, double b) { int tmp = (int)(BitConverter.DoubleToInt64Bits(a) >> 32); int tmp2 = (int)(b * (tmp - 1072632447) + 1072632447); ret

所以我在谷歌上搜索了很长时间,几乎什么也没找到。我从中找到了一些关于Math.Pow可能实现的信息,但这些信息不准确,例如这段代码

public static double PowerA(double a, double b)
{
    int tmp = (int)(BitConverter.DoubleToInt64Bits(a) >> 32);
    int tmp2 = (int)(b * (tmp - 1072632447) + 1072632447);
    return BitConverter.Int64BitsToDouble(((long)tmp2) << 32);
}
static void Main(string[] args)
{
    double x = 12.53, y = 16.45;
    Console.WriteLine(Math.Pow(x, y));
    Console.WriteLine(PowerA(x, y));
}
太不准确了


我认为它的工作原理类似于一系列的总和,但我不确定。

pow通常通过以下公式计算:

x^y = exp2(y*log2(x))
函数
exp2(x)、log2(x)
直接在FPU中实现。如果要实现bignums,还可以使用预计算的sqrt幂表,通过基本运算符对其进行评估,如:

2^1/2, 2^1/4, 2^1/8, 2^1/16, 2^1/32 ...
加快进程

如果您还需要处理负碱基的根,请参见以下内容:


这是强制性的。我确信在那篇文章中有一些你不知道的关于浮点运算的内容。如果你想的话,你可以下载与实际代码相当的代码。它已经有一段时间没有更新了,但是
Math.Pow
已经相当旧了。我认为PowerA是不准确的。PowerA(12.0,5.0)返回不正确的227008.5,而Math.Pow(12.0,5.0)返回正确的248832,该值足够小,可以进行测试。加上提升为整数倍的整数倍应该返回另一个整数倍,而不是以.5结尾的东西@RickDavin我读到的是OP所说的。他使用的方法没有正确镜像
Math.Pow
,这是不正确的,他正在寻找一个能够正确镜像
Math.Pow
。函数exp2(x),log2(x)直接在FPU中实现-这是我不知道的最重要的信息。函数exp2(x)、log2(x)直接在FPU中实现-您确定不是指FP库,因为FPU是一个硬件实体,随着CPU体系结构的变化而变化很大(不明确)并且可能不一定实现像这样的高阶函数。@我在
x87
FPU上工作的八位guru,这些函数本机存在,所以是的,我的意思是在FPU中实现,而不是在FP库中。@八位guru请参见
f2xm1、fyl2x、fyl2xp1
。。。我所说的“工作”是指“我和”粗俗的。。。我突然想到了错误的翻译:)@Spektre我想你没有抓住我的核心——并不是所有FPU架构都实现这种类型的高阶函数,因此断言“函数exp2(x),log2(x)直接在FPU中实现”是在假设硬件的性质,而这在问题中没有明确说明。
2^1/2, 2^1/4, 2^1/8, 2^1/16, 2^1/32 ...