C# C编译器“优化代码”:仅对代码片段禁用
我有一个C代码,当“优化代码”选项关闭时,该代码运行良好,但在其他情况下失败。是否有任何函数或类属性可以阻止函数或类的优化,但让编译器优化其他函数或类 我尝试了不安全或MethodImpl,但没有成功 谢谢 编辑: 我又做了一些测试。。。 代码如下所示:C# C编译器“优化代码”:仅对代码片段禁用,c#,compiler-optimization,C#,Compiler Optimization,我有一个C代码,当“优化代码”选项关闭时,该代码运行良好,但在其他情况下失败。是否有任何函数或类属性可以阻止函数或类的优化,但让编译器优化其他函数或类 我尝试了不安全或MethodImpl,但没有成功 谢谢 编辑: 我又做了一些测试。。。 代码如下所示: double arg = (Math.PI / 2d - Math.Atan2(a, d)); 当a=1且d=0时,arg应为0。 该代码是Excel通过ExcelDNA调用的函数 从优化的控制台应用程序调用相同的代码:确定 从Excel调
double arg = (Math.PI / 2d - Math.Atan2(a, d));
当a=1且d=0时,arg应为0。
该代码是Excel通过ExcelDNA调用的函数
从优化的控制台应用程序调用相同的代码:确定
从Excel调用此代码而不进行优化:确定
通过优化从Excel调用此代码:Not OK,arg==0为false,而arg是一个非常小的接近0的值,但不是0
调用函数之前的[MethodImplOptions.NoOptimization]的结果相同。这是处理浮点数据类型时得到的结果。你不能得到精确的0,但是一个非常接近的值,因为一个双精度的精度是有限的,并且不是每个值都能被表示出来,有时这些微小的精度误差加起来。您需要检查该值是否足够接近0 这就是处理浮点数据类型时得到的结果。你不能得到精确的0,但是一个非常接近的值,因为一个双精度的精度是有限的,并且不是每个值都能被表示出来,有时这些微小的精度误差加起来。您需要检查该值是否足够接近0 这很可能和Excel可能已经设置的有关-这意味着您的程序正在计算的浮点值略有不同,因为程序Excel托管您的程序集DLL。这可能会影响计算结果的方式,或自动强制为零的方式/值 为了确保您不会遇到不同浮点模式和/或错误的问题,您应该检查是否相等,而不是检查值是否非常接近 我还移植了重新解释整数比较,以防您发现它更适合处理更大的值
public class AlmostDoubleComparer : IComparer<double>
{
public static readonly AlmostDoubleComparer Default = new AlmostDoubleComparer();
public const double MaxUnitsInTheLastPlace = 3;
public static bool IsZero(double x)
{
return Compare(x, 0) == 0;
}
public static int Compare(double x, double y)
{
// Very important that cmp(x, y) == cmp(y, x)
if (Double.IsNaN(x) || Double.IsNaN(y))
return 1;
if (Double.IsInfinity(x) || Double.IsInfinity(y))
return 1;
var ix = DoubleInt64.Reinterpret(x);
var iy = DoubleInt64.Reinterpret(y);
var diff = Math.Abs(ix - iy);
if (diff < MaxUnitsInTheLastPlace)
return 0;
if (ix < iy)
return -1;
else
return 1;
}
int IComparer<double>.Compare(double x, double y)
{
return Compare(x, y);
}
}
[StructLayout(LayoutKind.Explicit)]
public struct DoubleInt64
{
[FieldOffset(0)]
private double _double;
[FieldOffset(0)]
private long _int64;
private DoubleInt64(long value)
{
_double = 0d;
_int64 = value;
}
private DoubleInt64(double value)
{
_int64 = 0;
_double = value;
}
public static double Reinterpret(long value)
{
return new DoubleInt64(value)._double;
}
public static long Reinterpret(double value)
{
return new DoubleInt64(value)._int64;
}
}
或者,您可以尝试和程序集进行比较,看看是否可以解决Excel的模式或它如何承载CLR的问题。这很可能与Excel可能已设置的模式有关-这意味着您的程序正在计算浮点值,这与Excel承载程序集DLL的程序略有不同。这可能会影响计算结果的方式,或自动强制为零的方式/值 为了确保您不会遇到不同浮点模式和/或错误的问题,您应该检查是否相等,而不是检查值是否非常接近 我还移植了重新解释整数比较,以防您发现它更适合处理更大的值
public class AlmostDoubleComparer : IComparer<double>
{
public static readonly AlmostDoubleComparer Default = new AlmostDoubleComparer();
public const double MaxUnitsInTheLastPlace = 3;
public static bool IsZero(double x)
{
return Compare(x, 0) == 0;
}
public static int Compare(double x, double y)
{
// Very important that cmp(x, y) == cmp(y, x)
if (Double.IsNaN(x) || Double.IsNaN(y))
return 1;
if (Double.IsInfinity(x) || Double.IsInfinity(y))
return 1;
var ix = DoubleInt64.Reinterpret(x);
var iy = DoubleInt64.Reinterpret(y);
var diff = Math.Abs(ix - iy);
if (diff < MaxUnitsInTheLastPlace)
return 0;
if (ix < iy)
return -1;
else
return 1;
}
int IComparer<double>.Compare(double x, double y)
{
return Compare(x, y);
}
}
[StructLayout(LayoutKind.Explicit)]
public struct DoubleInt64
{
[FieldOffset(0)]
private double _double;
[FieldOffset(0)]
private long _int64;
private DoubleInt64(long value)
{
_double = 0d;
_int64 = value;
}
private DoubleInt64(double value)
{
_int64 = 0;
_double = value;
}
public static double Reinterpret(long value)
{
return new DoubleInt64(value)._double;
}
public static long Reinterpret(double value)
{
return new DoubleInt64(value)._int64;
}
}
或者,您可以尝试对程序集进行测试,看看是否可以解决Excel的模式或它如何承载CLR的问题。失败是什么意思?您是否遇到异常,是执行缓慢还是其他原因?优化后,代码的功能不应更改。如果在启用优化后失败,则可能是错误的。。。请把密码贴出来!如果您尝试过MethodImpl.NoOptimization,但仍然失败,我怀疑您的问题是优化,我怀疑它会是什么,这是另外一回事。发布一些代码。尝试使用十进制而不是双精度。我认为使用十进制不是一个好主意,Excel传递的参数是双精度的,atan2传递的参数也是一样的。失败是什么意思?您是否遇到异常,是执行缓慢还是其他原因?优化后,代码的功能不应更改。如果在启用优化后失败,则可能是错误的。。。请把密码贴出来!如果您尝试过MethodImpl.NoOptimization,但仍然失败,我怀疑您的问题是优化,我怀疑它会是什么,这是另外一回事。发布一些代码。尝试使用十进制而不是双精度。我认为使用十进制不是一个好主意,Excel传递的参数是双精度的,atan2的参数也是一样。我认为将十进制或int与Math.atan2一起使用没有意义。使用十进制并不会神奇地给你们无限精度,它只是让你们精确地表示小数点。我什么时候说过十进制会提供无限精度的?这也取决于他想用它做什么。结果是一个非常小的值,你不能对不精确性做任何改变。将双精度值与常量值(如0)进行比较通常会导致此类错误。是的,使用双精度值会导致此类错误。但使用十进制有什么帮助呢?它可以最大限度地减少舍入误差,但你是对的,在这种情况下可能没有帮助。你不能得到精确的0,但得到非常接近的值
e=>ok,但为什么在optim打开的情况下从Excel调用时,arg==0为false,而在optim关闭的情况下,arg==0对于相同的参数为true?我认为将decimal或int与Math.Atan2一起使用没有意义。使用十进制并不会神奇地给你们无限精度,它只是让你们精确地表示小数点。我什么时候说过十进制会提供无限精度的?这也取决于他想用它做什么。结果是一个非常小的值,你不能对不精确性做任何改变。将双精度值与常量值(如0)进行比较通常会导致此类错误。是的,使用双精度值会导致此类错误。但是使用十进制有什么帮助呢?它可以最大限度地减少舍入误差,但是你是对的,在这种情况下可能没有帮助。你没有得到精确的0,但是一个非常接近的值=>ok,但是为什么在启用optim的情况下从Excel调用时,arg==0为false,而在禁用optim时,对于相同的参数,arg==0为真?这很可能与Excel设置的浮点模式有关=>感谢链接,我会检查的。@Poca请记住,如果您将其更改回您期望的值,我不确定默认值是什么,您可能会弄乱Excel-因此最好进行“接近度”检查。这很可能与Excel设置的浮点模式有关=>感谢链接,我会检查的。@Poca请记住,如果您将其更改回您期望的值,我不确定默认值是什么,您可能会弄乱Excel-因此最好进行“接近度”检查。