复数显示为非常小的小数。

huangapple go评论77阅读模式
英文:

Complex number displaying as incredibly small decimal

问题

使用了MathNet库中的一个方法,尝试应用其立方根查找函数,但它输出了非常长的小数,而四舍五入似乎不会影响它们。

public static (Complex, Complex, Complex) FindCubic(double a, double b, double c, double d)
{
	double num = b * b - 3.0 * a * c;
	double num2 = 2.0 * b * b * b - 9.0 * a * b * c + 27.0 * a * a * d;
	double num3 = -1.0 / (3.0 * a);
	if ((num2 * num2 - 4.0 * num * num * num) / (-27.0 * a * a) == 0.0)
	{
		if (num == 0.0)
		{
			Complex complex = new Complex(num3 * b, 0.0);
			return (complex, complex, complex);
		}
		Complex complex2 = new Complex((9.0 * a * d - b * c) / (2.0 * num), 0.0);
		Complex item = new Complex((4.0 * a * b * c - 9.0 * a * a * d - b * b * b) / (a * num), 0.0);
		return (complex2, complex2, item);
	}
	(Complex, Complex, Complex) tuple = ((num == 0.0) ? new Complex(num2, 0.0).CubicRoots() : ((num2 + Complex.Sqrt(num2 * num2 - 4.0 * num * num * num)) / 2.0).CubicRoots());
	return (num3 * (b + tuple.Item1 + num / tuple.Item1), num3 * (b + tuple.Item2 + num / tuple.Item2), num3 * (b + tuple.Item3 + num / tuple.Item3));
}

上述代码运行正常,但不太确定如何缩短结果中的小数部分。例如,如果理论上输出应该是(-1, 0)(在大多数计算器上确实如此显示),但实际上它显示为(-1, -2.0354088784794536E-16),这接近于0,并且应该显示为0。

Round(num3, 0) * (b + new Complex (Round(tuple.Item1.Real, 0), Round(tuple.Item1.Imaginary, 0)) + num / tuple.Item1)

上述是相关的四舍五入代码,因为你不能直接对复数进行四舍五入。

评论中解决:忘记了浮点数不精确性。

英文:

Was using a method from the MathNet Library and tried applying its Cubic root finding function, but it outputs incredibly long decimals, and rounding doesn't seem to affect them.

public static (Complex, Complex, Complex) FindCubic(double a, double b, double c, double d)
{
	double num = b * b - 3.0 * a * c;
	double num2 = 2.0 * b * b * b - 9.0 * a * b * c + 27.0 * a * a * d;
	double num3 = -1.0 / (3.0 * a);
	if ((num2 * num2 - 4.0 * num * num * num) / (-27.0 * a * a) == 0.0)
	{
		if (num == 0.0)
		{
			Complex complex = new Complex(num3 * b, 0.0);
			return (complex, complex, complex);
		}
		Complex complex2 = new Complex((9.0 * a * d - b * c) / (2.0 * num), 0.0);
		Complex item = new Complex((4.0 * a * b * c - 9.0 * a * a * d - b * b * b) / (a * num), 0.0);
		return (complex2, complex2, item);
	}
	(Complex, Complex, Complex) tuple = ((num == 0.0) ? new Complex(num2, 0.0).CubicRoots() : ((num2 + Complex.Sqrt(num2 * num2 - 4.0 * num * num * num)) / 2.0).CubicRoots());
	return (num3 * (b + tuple.Item1 + num / tuple.Item1), num3 * (b + tuple.Item2 + num / tuple.Item2), num3 * (b + tuple.Item3 + num / tuple.Item3));
}

The code above works fine, but really not sure how to shorten the decimals in the results. For example if the output should be (-1, 0) in theory (and it does display so on most calculators), it instead displays (-1, -2.0354088784794536E-16), which is close to 0, and should be displayed as 0.

Round(num3, 0) * (b + new Complex (Round(tuple.Item1.Real, 0), Round(tuple.Item1.Imaginary, 0)) + num / tuple.Item1)

The rounding code in question since you can't directly round complex numbers.

Solved in comment: Forgot about floating point inaccuracy.

答案1

得分: 4

关于你得到的答案没有特别大的问题。请记住,浮点数计算本质上是近似的。实际上,点 (1,0)(1, -2.0354088784794536E-16) 之间的距离小于 1ulp(最小精度单位)。大多数计算器为了避免出现不愉快的输出会多计算几位小数并将结果四舍五入以适应显示。

至于你的四舍五入代码,它是针对中间结果而不是最终答案的:

Round(num3, 0) * (b + new Complex (Round(tuple.Item1.Real, 0), Round(tuple.Item1.Imaginary, 0)) + num / tuple.Item1)

你想要的是像这样的东西:

int digits = 8;
Complex tmp = num3 * (b + tuple.Item1 + num / tuple.Item1);
tmp = new Complex(Round(tmp.Real, digits), Round(tmp.Imaginary, digits));

不过最佳做法是让格式化程序进行四舍五入,请参考这里

英文:

There's nothing particularly wrong with the answer you get. Remember that floating point calculations are inherently approximate. Indeed, the distance between (1,0) and (1, -2.0354088784794536E-16) is less than 1ulp. What most calculators do to avoid such unpleasant outputs is to calculate with a couple extra digits and round the result to fit the display.

As for your rounding code, it rounds intermediary results rather than the final answer:

Round(num3, 0) * (b + new Complex (Round(tuple.Item1.Real, 0), Round(tuple.Item1.Imaginary, 0)) + num / tuple.Item1)

What you want instead is something like this:

int digits = 8;
Complex tmp = num3 * (b + tuple.Item1 + num / tuple.Item1);
tmp = new Complex(Round(tmp.Real, digits), Round(tmp.Imaginary, digits));

Though the best practice would be to let the rounding happen in the formatting routine.

huangapple
  • 本文由 发表于 2023年5月29日 11:40:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76354556.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定