これは、Excelが設定している可能性が高いfloating point modeと非常によく似ています。これは、アセンブリ(DLL)をホストしているプログラム(Excel)によってプログラムが浮動小数点数をわずかに差し引いていることを意味します。これは、結果がどのように計算されるか、またはどのような値が自動的に0に強制的に強制されるかに影響を与える可能性があります。
異なる浮動小数点モードおよび/またはエラーの問題に遭遇することは絶対に避けてください。値が非常に近いかどうかをチェックすることで、等価性を確認する必要があります。 This is not really a hack.
public class AlmostDoubleComparer : IComparer<double>
{
public static readonly AlmostDoubleComparer Default = new AlmostDoubleComparer();
public const double Epsilon = double.Epsilon * 64d; // 0.{322 zeroes}316
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 absX = Math.Abs(x);
var absY = Math.Abs(y);
var diff = absX > absY ? absX - absY : absY - absX;
if (diff < Epsilon)
return 0;
if (x < y)
return -1;
else
return 1;
}
int IComparer<double>.Compare(double x, double y)
{
return Compare(x, y);
}
}
// E.g.
double arg = (Math.PI/2d - Math.Atan2(a, d));
if (AlmostDoubleComparer.IsZero(arg))
// Regard it as zero.
(それはより一貫大きな値を扱う)私はまた、再解釈した整数の比較を移植した場合には、あなたはそれがより適切な見つけます。
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;
}
}
また、あなたがしようとNGenアセンブリを、あなたはExcelが持っているモード、またはどのようにそれがCLRをホストしているのいずれかを回避することができるかどうかを確認できます。
「失敗」とはどういう意味ですか?あなたは例外を取得しますか、それはゆっくり実行するのでしょうか?コードの機能は最適化されても変更されるべきではありません。 – Botz3000
最適化を有効にしたときにエラーが発生した場合は、間違っている可能性があります...コードを投稿してください! –
'MethodImpl.NoOptimization'を試してもまだ失敗している場合は、あなたの問題が最適化であると疑います。いくつかのコードを投稿してください。 –