C# Complex Tanh 对于大值失败
C# Complex Tanh fails for large values
这是 Microsoft 对 Complex
的 Sinh
的实施
public static Complex Sinh(Complex value) /* Hyperbolic sin */
{
double a = value.m_real;
double b = value.m_imaginary;
return new Complex(Math.Sinh(a) * Math.Cos(b), Math.Cosh(a) * Math.Sin(b));
}
和 Cosh
的实施
public static Complex Cos(Complex value) {
double a = value.m_real;
double b = value.m_imaginary;
return new Complex(Math.Cos(a) * Math.Cosh(b), - (Math.Sin(a) * Math.Sinh(b)));
}
最后是 Tanh
的实现
public static Complex Tanh(Complex value) /* Hyperbolic tan */
{
return (Sinh(value) / Cosh(value));
}
来源:https://referencesource.microsoft.com/System.Numerics/a.html#e62f37ac1d0c67da
我不明白为什么 Microsoft 以这种方式实施 Tanh
方法?
对于非常大的值,它将失败。例如:
tanh(709 + 0i) --> 1
, 好的
tanh(711 + 0i) --> NaN
,失败应该是1
关于如何改进 tanh
方法的任何想法?
对于 double
,Math.Tanh
方法适用于较大的值。
复杂的tanh
方法可以这样实现:
public static Complex Tanh(Complex value)
{
double a = value.Real;
double b = value.Imaginary;
double tanh_a = Math.Tanh(a);
double tan_b = Math.Tan(b);
Complex num = new Complex(tanh_a, tan_b);
Complex den = new Complex(1, tanh_a * tan_b);
return num / den;
}
这也适用于较大的值,请参阅 https://dotnetfiddle.net/xGWdQt。
更新
同样需要重新实现复杂的 tan
方法,因为它适用于较大的值(虚部):
public static Complex Tan(Complex value)
{
double a = value.Real;
double b = value.Imaginary;
double tan_a = Math.Tan(a);
double tanh_b = Math.Tanh(b);
Complex num = new Complex(tan_a, tanh_b);
Complex den = new Complex(1, -tan_a * tanh_b);
return num / den;
}
使用 Hans Passant 的评论另一种实现 tanh
方法的方法是:
public static Complex Tanh(Complex value)
{
if (Math.Abs(value.Real) > 20)
return new Complex(Math.Sign(value.Real), 0);
else
return Complex.Tanh(value);
}
参见 https://dotnetfiddle.net/QvUECX。
和tan
方法:
public static Complex Tan(Complex value)
{
if (Math.Abs(value.Imaginary) > 20)
return new Complex(0, Math.Sign(value.Imaginary));
else
return Complex.Tan(value);
}
这是 Microsoft 对 Complex
Sinh
的实施
public static Complex Sinh(Complex value) /* Hyperbolic sin */
{
double a = value.m_real;
double b = value.m_imaginary;
return new Complex(Math.Sinh(a) * Math.Cos(b), Math.Cosh(a) * Math.Sin(b));
}
和 Cosh
public static Complex Cos(Complex value) {
double a = value.m_real;
double b = value.m_imaginary;
return new Complex(Math.Cos(a) * Math.Cosh(b), - (Math.Sin(a) * Math.Sinh(b)));
}
最后是 Tanh
public static Complex Tanh(Complex value) /* Hyperbolic tan */
{
return (Sinh(value) / Cosh(value));
}
来源:https://referencesource.microsoft.com/System.Numerics/a.html#e62f37ac1d0c67da
我不明白为什么 Microsoft 以这种方式实施 Tanh
方法?
对于非常大的值,它将失败。例如:
tanh(709 + 0i) --> 1
, 好的tanh(711 + 0i) --> NaN
,失败应该是1
关于如何改进 tanh
方法的任何想法?
对于 double
,Math.Tanh
方法适用于较大的值。
复杂的tanh
方法可以这样实现:
public static Complex Tanh(Complex value)
{
double a = value.Real;
double b = value.Imaginary;
double tanh_a = Math.Tanh(a);
double tan_b = Math.Tan(b);
Complex num = new Complex(tanh_a, tan_b);
Complex den = new Complex(1, tanh_a * tan_b);
return num / den;
}
这也适用于较大的值,请参阅 https://dotnetfiddle.net/xGWdQt。
更新
同样需要重新实现复杂的 tan
方法,因为它适用于较大的值(虚部):
public static Complex Tan(Complex value)
{
double a = value.Real;
double b = value.Imaginary;
double tan_a = Math.Tan(a);
double tanh_b = Math.Tanh(b);
Complex num = new Complex(tan_a, tanh_b);
Complex den = new Complex(1, -tan_a * tanh_b);
return num / den;
}
使用 Hans Passant 的评论另一种实现 tanh
方法的方法是:
public static Complex Tanh(Complex value)
{
if (Math.Abs(value.Real) > 20)
return new Complex(Math.Sign(value.Real), 0);
else
return Complex.Tanh(value);
}
参见 https://dotnetfiddle.net/QvUECX。
和tan
方法:
public static Complex Tan(Complex value)
{
if (Math.Abs(value.Imaginary) > 20)
return new Complex(0, Math.Sign(value.Imaginary));
else
return Complex.Tan(value);
}