我有一个单元测试,测试边界:
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void CreateExtent_InvalidTop_ShouldThrowArgumentOutOfRangeException()
{
var invalidTop = 90.0 + Double.Epsilon;
new Extent(invalidTop, 0.0, 0.0, 0.0);
}
public static readonly double MAX_LAT = 90.0;
public Extent(double top, double right, double bottom, double left)
{
if (top > GeoConstants.MAX_LAT)
throw new ArgumentOutOfRangeException("top"); // not hit
}我想我应该把90.0抛到边缘,给它加上最小可能的正数,但是现在没有抛出异常,知道为什么吗?
当调试时,我认为顶部是90,当它应该是90.00000000.某物。
编辑:--我应该再仔细想想,90+Double.Epsilon会失去它的分辨率。似乎最好的方法是做一些改变。
解决方案:
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void CreateExtent_InvalidTop_ShouldThrowArgumentOutOfRangeException()
{
var invalidTop = Utility.IncrementTiny(90); // 90.000000000000014
// var sameAsEpsilon = Utility.IncrementTiny(0);
new Extent(invalidTop, 0, 0, 0);
}
/// <summary>
/// Increment a double-precision number by the smallest amount possible
/// </summary>
/// <param name="number">double-precision number</param>
/// <returns>incremented number</returns>
public static double IncrementTiny(double number)
{
#region SANITY CHECKS
if (Double.IsNaN(number) || Double.IsInfinity(number))
throw new ArgumentOutOfRangeException("number");
#endregion
var bits = BitConverter.DoubleToInt64Bits(number);
// if negative then go opposite way
if (number > 0)
return BitConverter.Int64BitsToDouble(bits + 1);
else if (number < 0)
return BitConverter.Int64BitsToDouble(bits - 1);
else
return Double.Epsilon;
}
/// <summary>
/// Decrement a double-precision number by the smallest amount possible
/// </summary>
/// <param name="number">double-precision number</param>
/// <returns>decremented number</returns>
public static double DecrementTiny(double number)
{
#region SANITY CHECKS
if (Double.IsNaN(number) || Double.IsInfinity(number))
throw new ArgumentOutOfRangeException("number");
#endregion
var bits = BitConverter.DoubleToInt64Bits(number);
// if negative then go opposite way
if (number > 0)
return BitConverter.Int64BitsToDouble(bits - 1);
else if (number < 0)
return BitConverter.Int64BitsToDouble(bits + 1);
else
return 0 - Double.Epsilon;
}这就是我的工作。
发布于 2014-12-16 14:10:49
每Double.Epsilon
Epsilon属性的值反映了在数值运算或比较
DoubleDouble实例的值为零()时对数值操作或比较具有重要意义的最小正值。
(强调我的)
将其添加到90.0不会产生“90.0之后的下一个最小值”,这将再次产生90.0。
发布于 2014-12-16 14:13:10
Double.Epsilon是最小的正可表示值。仅仅因为它本身是可表示的,并不意味着它是任何其他可表示值与第二个最高值之间的最小值。
假设您有一个表示整数的系统。您可以表示任何整数到5个有效数字,以及一个标度(例如,在1-100范围内)。
因此,这些值是完全可表示的,例如
在那个系统中,"epsilon“值应该是1.但是,如果将1到12345000相加,那么最终的结果仍然是12345000,因为系统无法表示12345001的确切结果。
现在,将同样的逻辑应用于double,以及它的所有复杂之处,您将得到一个小得多的epsilon,但同样的一般原理:一个与零不同的值,但当将更大的数字相加时,它仍然不会产生任何差别。
请注意,大得多的值也具有相同的属性--例如,如果x是一个非常大的double,那么x + 1很可能等于x,因为两个“相邻”双值之间的差距随着值的增大而超过2。
发布于 2014-12-16 21:03:47
在C99和C++中,执行您想要做的事情的函数称为nextafter,在math.h中。我不知道C#是否有类似的名称,但如果有,我希望它有一个类似的名称。
https://stackoverflow.com/questions/27506477
复制相似问题