我在VB中有这个代码行:
Dim Sqrt As Double Sqrt = Radius ^ 2 - (CenterX - X) ^ 2
上述声明中的参数正在传递以下值:
X= -7.3725025845036161 Double CenterX =0.0 Double Radius= 8.0 Double
执行上述声明时,Sqrt的值为:
Sqrt 9.646205641487505 Double
现在我用Math类写了一个类似的C#逻辑:
double Sqrt = 0; Sqrt = Math.Pow(Radius,2) - Math.Pow((CenterX - X),2);
Sqrt 9.6462056414874979 double
我需要帮助,因为这个单一的C#代码更改,我的所有价值观都受到影响。有什么可以做的,以获得与* VB *源代码相似的价值?
有一个
difference in the precision between the VB6 and the .NET double type.两者都是IEEE 64位双精度类型,但.NET CLR在内部使用80位扩展精度,即您的计算在.NET中更准确。
如果您必须向下兼容VB6精度,您可以强制您的FPU(浮点单元)使用(不太准确的)64位值。这可以使用本机_controlfp_s
功能实现。
以下是一个代码片段,您可以暂时“降级”浮点精度以实现向后兼容。您可以这样使用它:
// default floating point precision using (new FloatingPoint64BitPrecision()) { // floating-point precision is set to 64 bit } // floating-point precision is reset to default
代码段
/// <summary> /// This class changes floating-point precision to 64 bit /// </summary> internal class FloatingPoint64BitPrecision : IDisposable { private readonly bool _resetrequired; public FloatingPoint64BitPrecision() { int fpFlags; var errno = SafeNativeMethods._controlfp_s(out fpFlags,0); if (errno != 0) { throw new Win32Exception( errno,"Unable to retrieve floating-point control flag."); } if ((fpFlags & SafeNativeMethods._MCW_PC) != SafeNativeMethods._PC_64) { Trace.WriteLine("Change floating-point precision to 64 bit"); errno = SafeNativeMethods._controlfp_s( out fpFlags,SafeNativeMethods._PC_64,SafeNativeMethods._MCW_PC); if (errno != 0) { throw new Win32Exception( errno,"Unable to change floating-point precision to 64 bit."); } _resetrequired = true; } } public void Dispose() { if (_resetrequired) { Trace.WriteLine("Resetting floating-point precision to default"); SafeNativeMethods._fpreset(); } } } internal static class SafeNativeMethods { [DllImport("msvcr120.dll")] public static extern void _fpreset(); [DllImport("msvcr120.dll",CallingConvention = CallingConvention.Cdecl)] public static extern int _controlfp_s( out int currentControl,int newControl,int mask); public static int _CW_DEFAULT = (_RC_NEAR | _PC_53 | _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT | _EM_DENORMAL); public const int _MCW_EM = 0x0008001f; // interrupt Exception Masks public const int _EM_INEXACT = 0x00000001; // inexact (precision) public const int _EM_UNDERFLOW = 0x00000002; // underflow public const int _EM_OVERFLOW = 0x00000004; // overflow public const int _EM_ZERODIVIDE = 0x00000008; // zero divide public const int _EM_INVALID = 0x00000010; // invalid public const int _EM_DENORMAL = 0x00080000; // denormal exception mask // (_control87 only) public const int _MCW_RC = 0x00000300; // Rounding Control public const int _RC_NEAR = 0x00000000; // near public const int _RC_DOWN = 0x00000100; // down public const int _RC_UP = 0x00000200; // up public const int _RC_CHOP = 0x00000300; // chop public const int _MCW_PC = 0x00030000; // Precision Control public const int _PC_64 = 0x00000000; // 64 bits public const int _PC_53 = 0x00010000; // 53 bits public const int _PC_24 = 0x00020000; // 24 bits public const int _MCW_IC = 0x00040000; // Infinity Control public const int _IC_AFFINE = 0x00040000; // affine public const int _IC_PROJECTIVE = 0x00000000; // projective }