c#和复数的奇异幂
本文关键字: | 更新日期: 2023-09-27 18:17:57
我一直在c#中玩复数,我发现了一些有趣的事情。不确定这是一个bug还是我刚刚错过了一些东西,但是当我运行以下代码:
var num = new Complex(0, 1);
var complexPow = Complex.Pow(num, 2);
var numTimesNum = num * num;
Console.WriteLine("Complex.Pow(num, 2) = {0} num*num = {1}", complexPow.ToString(), numTimesNum.ToString());
得到以下输出:
Complex.Pow(num, 2) = (-1, 1.22460635382238E-16) num*num = (-1, 0)
如果内存有限,一个复数乘以它自己应该是-1,没有虚数部分(或者虚数部分是0)。Pow(num, 2)给出-1?1.22460635382238E-16从何而来?
如果它的问题,我使用单声道,因为我不是在Windows atm。我认为它可能是64位的,因为我正在运行64位的操作系统,但我不确定在哪里检查。
照顾,克尔。
编辑:好吧,我解释得不好。I的意思是I的平方是-1,而不是任何复数的平方。谢谢你指出来。我现在有点累,所以我的大脑不太好使,哈哈。
编辑2:为了澄清一些事情,我最近一直在阅读一些数学,并决定做一个有趣的小脚本语言。好吧,"脚本语言"是一个过度陈述,它只是计算方程,没有别的。
您看到的是浮点不精确
1.22460635382238E-16
实际上是0.00000000000000012...
。
Complex.Pow()
可能是通过De Moivre公式实现的,使用三角函数计算任意幂。
因此,它受到浮点算术和三角函数的不准确性的影响。
显然,它没有任何积分幂的特殊情况代码,这可以更简单。
普通的复数乘法只涉及简单的算术,所以当数字是整数时,它不受浮点不精度的影响。
为什么不复杂。Pow(num, 2)给出-1?1.22460635382238E-16从何而来?
我怀疑这基本上是一个舍入误差。毕竟这是一个很小的数字。我不知道Complex.Pow
的细节,但如果我发现它在某处使用了一些三角函数,我一点也不会感到惊讶——你可能会很好地观察到pi/2不能完全表示为双精度数。
*
操作可以通过更简单的定义来避免这种情况- Complex.Pow
可以对进行特殊处理,仅使用x * x
,其中幂为2,但我希望没有这样做。相反,使用了一种通用算法,该算法给出的答案非常接近假设的答案,但可能导致小错误。
为什么不复杂。Pow(num, 2)给出-1?1.22460635382238E-16从何而来?
浮点表示的标准问题,以及用于计算Complex.Pow
的算法(它不像你想象的那么简单)。注意,1.22460635382238E-16
非常小,接近机器epsilon。此外,这里的一个关键事实是(0, 1)
在极坐标系中实际上是(1, pi / 2)
,而pi / 2
在浮点数中没有精确的表示。
如果这让你感到不舒服,我建议你阅读《每个计算机科学家都应该知道的浮点算术》。 应该成为大学计算机科学课程的必读书目。