c++;和具有大值的c#sin函数
当我使用大数时,我在C#中遇到了这种奇怪的数学行为;例如: C#:.Net 4.7.2:Math.Sin(6.2831853071795856E+45)=6.2831853071795856E+45 C++:sin(6.2831853071795856E+45)=-0.089650623841643268 有什么办法能得到与C+++< /p >相同的结果? C#样本:c++;和具有大值的c#sin函数,c#,c++,.net,floating-point,.net-4.7.2,C#,C++,.net,Floating Point,.net 4.7.2,当我使用大数时,我在C#中遇到了这种奇怪的数学行为;例如: C#:.Net 4.7.2:Math.Sin(6.2831853071795856E+45)=6.2831853071795856E+45 C++:sin(6.2831853071795856E+45)=-0.089650623841643268 有什么办法能得到与C+++< /p >相同的结果? C#样本: 双值=6.2831853071795856E+45; Console.WriteLine(Math.Sin(value));
双值=6.2831853071795856E+45;
Console.WriteLine(Math.Sin(value));
C++示例:
double x=6.2831853071795856E+45;
双重结果;
结果=sin(x);
cout6.2831853071795856E+45等大数的分布;毫无意义。请记住,圆周率约为3.14,浮点数可能为(有关更多信息,请参阅)
计算出的数字可能完全错误。
考虑使用像C或C++代码这样的静态分析工具。或者像这样的动态工具
根据经验,像sin
,cos
,tan
这样的三角函数不应与大数字一起使用(例如,大于π的几千倍ℼ = 绝对值为3.14)
否则,使用bignum库,如。它将使计算速度降低数千倍,但它可以为sin(pi*1.e+45)
请阅读一些关于(它们与三角函数有关)
还可以尝试使用“可视化”函数sin
(对于合理的数字)
从数学上讲,每个有限实数的sin
介于-1和1之间。所以Math.Sin(6.2831853071795856E+45)=6.2831853071795856E+45是错误的
另请阅读像和这样的会议论文。作为旁注,sin/cos/tan的计算方法在.NET中发生了变化。事件发生在2016年6月2日,发生在.NET Core上。正如作者在书中所写:
AMD64窗口上的Sin、Cos和Tan以前是在vm\AMD64\JitHelpers\u Fast.asm中实现的
调用x87浮点代码(fsin、fcos、fptan),因为CRT帮助程序太慢。这
不再如此,所有平台都使用CRT调用
请注意,CRT是C语言运行库。这解释了为什么.NET内核的更新版本在同一平台< /强>中使用与C++ +<强>相同的结果。他们正在使用与其他C++程序相同的CRT。
为感兴趣的人准备的“旧”代码的最后版本:和
尚不清楚.NET Framework是否/何时继承了这些更改。从一些测试看来
.NET核心>=2.0(尚未测试以前的版本):Math.Sin(6.2831853071795856E+45)==0.824816390616968
.NETFramework 4.8(32位和64位):Math.Sin(6.2831853071795856E+45)==6.28318530717959E+45
所以它没有继承他们
有趣的附录
做了一些检查,发现Math.Sin(6.2831853071795856E+45)=6.28318530717959E+45
是fsin
汇编操作码的“官方”答案,所以它是英特尔(大约1980年)关于6.2831853071795856E+45的Sin是多少的“官方”答案,所以如果你使用英特尔,你必须相信Math.Sin(6.2831853071795856E+45)==6.28318530717959E+45,否则你就是叛徒!两个答案都大错特错,但你提出的问题可能会给你带来麻烦。
罪的真正价值(6.2831853071795856 × 10⁴⁵) 约为0.09683996046341126;此近似值与真实值相差小于10⁻¹⁶ 真实值的一部分。(我使用165位中间精度计算了这个近似值。)
但是,你不能通过C++的函数来签名,它的签名是“代码>公共静态双罪恶(双A)< />代码,或者是C++函数,签名为代码>双罪恶(double)< /代码>。为什么?6.2831853071795856 × 10⁴⁵ 不是IEEE 754二进制64或“双精度”浮点数,因此您最多只能了解附近浮点数的罪恶。最接近的浮点数,以及通常在程序中键入
6.2831853071795856E+45
得到的是6283185307179585571582855233194226059181031424,与6.283不同1853071795856 × 10⁴⁵ 28417144766805773940818968576≈ 2.84 × 10²⁸.
IEEE 754二进制64浮点数628318530717958557158285523194226059181031424与6.2831853071795856非常接近 × 10⁴⁵ 相对误差(相差小于10⁻¹⁷ 部分为真值),但绝对误差~2.84 × 10²⁸ 远超过周期2f(x)=sin(x)在正负1之间振荡,周期为2*pi,即sin(x)=sin(N*2*pi+x)
暂时忘掉编程语言,忘掉sin(),想想科学符号1.23E+45中的值是什么意思。它可以表示从1225000…(41个零)到1234999…(42个九)的任何值,即1E43个可能的整数(或者如果允许分数,则表示无限个值)
在这里,我通过使用十进制术语和精确地等于有效数字来严格定义。请在此处查找链接以了解更多信息:。我也希望我的指数算术正确,但不管怎样,其含义应该是清楚的
回到SN(),C和C++:由于纯数学函数输出每2×PI(6.28)重复,并且双精度浮点(IEEE 754位64加倍)在C和C++中只有15到17个显著的十进制数字,<强>没有输出(SN)函数可能是有意义的,因为输入值“丢失”(不精确)至少有30个有效/相关的十进制数字
您确定您的数字正确吗?首先,sin函数的返回值必须介于0和1之间…好的,如果我可以将我的观察添加到这个有趣的主题:。以及,嗯,编译器错误?以及