首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么将double.epsilon添加到一个值中会产生相同的值,完全相等?

为什么将double.epsilon添加到一个值中会产生相同的值,完全相等?
EN

Stack Overflow用户
提问于 2014-12-16 14:05:44
回答 4查看 2.7K关注 0票数 22

我有一个单元测试,测试边界:

代码语言:javascript
复制
[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会失去它的分辨率。似乎最好的方法是做一些改变。

解决方案:

代码语言:javascript
复制
[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;
}

这就是我的工作。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-12-16 14:10:49

Double.Epsilon

Epsilon属性的值反映了在数值运算或比较Double Double实例的值为零()时对数值操作或比较具有重要意义的最小正值。

(强调我的)

将其添加到90.0不会产生“90.0之后的下一个最小值”,这将再次产生90.0。

票数 26
EN

Stack Overflow用户

发布于 2014-12-16 14:13:10

Double.Epsilon是最小的正可表示值。仅仅因为它本身是可表示的,并不意味着它是任何其他可表示值与第二个最高值之间的最小值。

假设您有一个表示整数的系统。您可以表示任何整数到5个有效数字,以及一个标度(例如,在1-100范围内)。

因此,这些值是完全可表示的,例如

  • 12345 (digits=12345,标度= 0)
  • 12345000 (digits=12345,标度= 3)

在那个系统中,"epsilon“值应该是1.但是,如果将1到12345000相加,那么最终的结果仍然是12345000,因为系统无法表示12345001的确切结果。

现在,将同样的逻辑应用于double,以及它的所有复杂之处,您将得到一个小得多的epsilon,但同样的一般原理:一个与零不同的值,但当将更大的数字相加时,它仍然不会产生任何差别。

请注意,大得多的值也具有相同的属性--例如,如果x是一个非常大的double,那么x + 1很可能等于x,因为两个“相邻”双值之间的差距随着值的增大而超过2。

票数 21
EN

Stack Overflow用户

发布于 2014-12-16 21:03:47

在C99和C++中,执行您想要做的事情的函数称为nextafter,在math.h中。我不知道C#是否有类似的名称,但如果有,我希望它有一个类似的名称。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27506477

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档