![](/img/trans.png)
[英]An efficient way to implement power function: Why Math.Exp(x * Math.Log(n)) is faster than Math.Pow()?
[英]Is Math.Log implemented in a way to avoid loss of precision for log(1 + x)?
我正在將一些C#代碼轉換為C ++,其中包含Math.Log(1 + x)
的Math.Log(1 + x)
,其中x可以是一個非常小的值,接近於零。 我遇到了建議(在C ++中),建議在處理log(1 + x)
時使用std::log1p
,其中x
接近零,即避免精度損失 。
C#/。NET Math.Log
方法是否以類似避免精度損失的方式實現? 我找不到.NET API參考中引用的類似Math.Log1p()
函數。
不,Math.Log()使用C庫函數log()完成其工作。 實際上,log1p()包含在CLR使用的CRT庫中,但未通過框架公開。 您可以使用pinvoke聲明來解決此問題:
using System;
using System.Runtime.InteropServices;
public static class Math {
public static double Log1p(double arg) {
if (arg < -1.0) throw new ArgumentException();
return log1p(arg);
}
[DllImport("msvcr120_clr0400.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern double log1p(double arg);
}
如果您需要的目標是.NET版本低於4.0,則可以考慮將DllImport聲明更改為使用“ ucrtbase.dll”。
可能值得注意的是,我無法在此代碼上獲得一致的性能。 將x64放在我的便攜式筆記本電腦上的C#和C上,每次調用約140納秒。 但是在將x86定位為225與40時,看到了很大的不同。巨大的不同,我對此沒有很好的解釋。
double VerySmall = .0000000000000002;
double TooSmall = .0000000000000001;
Console.WriteLine("{0} {1} {2}", Math.Log(1 + VerySmall), Math.Log(1 + TooSmall), log1p(TooSmall));
static double log1p(double x)
=> Math.Abs(x) > 1e-4 ? Math.Log(1.0 + x) : (-0.5 * x + 1.0) * x;
在Windows上運行的.NET Framework 4.6.1中,此代碼的輸出為:
2.22044604925031E-16 0 1E-16
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.