我有一个 double f ,想要一个稍微大一点(或更小)的方法来获得一个尽可能接近的新值到原件但仍然严格大于(或小于)原件。

它不必靠近最后一位—更重要的是,无论我做出什么改变,都能保证产生不同的值,而不是回到原来的位置。

有帮助吗?

解决方案

检查math.h文件。如果你很幸运,你有 nextafter nextafterf 定义的功能。它们以便携式和平台无关的方式完成您想要的工作,并且是C99标准的一部分。

另一种方法(可能是后备解决方案)是将你的浮点数分解为尾数和指数部分。增量很简单:只需在尾数中添加一个即可。如果出现溢出,则必须通过递增指数来处理此问题。减少的方式也是一样的。

编辑:正如评论中指出的那样,只需在其二进制表示中增加浮点数就足够了。尾数溢出将增加指数,这正是我们想要的。

简而言之,这与nextafter相同。

但这不是完全可移植的。你不得不处理endianess以及并非所有机器都有IEEE浮动的事实(好的 - 最后一个原因是更具学术性)。

处理NAN和infinite也有点棘手。你不能简单地增加它们,因为它们是定义而不是数字。

其他提示

u64 &x = *(u64*)(&f);
x++;

是的,认真的。

编辑:正如有人指出的那样,这并不能正确处理-ve数字,Inf,Nan或溢出。以上更安全的版本是

u64 &x = *(u64*)(&f);
if( ((x>>52) & 2047) != 2047 )    //if exponent is all 1's then f is a nan or inf.
{
    x += f>0 ? 1 : -1;
}

从绝对意义上讲,您可以添加到浮点值以创建新的不同值的最小量将取决于值的当前大小;它将是类型的机器epsilon 乘以当前指数。

查看 IEEE规范了解浮点表示。最简单的方法是将值重新解释为整数类型,添加1,然后检查(如果您关心)您没有翻转符号或通过检查符号和指数位生成NaN。

或者,您可以使用 frexp 获取当前的尾数和指数,因此计算要添加的值。

我需要做同样的事情并提出这段代码:

double DoubleIncrement(double value)
{
  int exponent;
  double mantissa = frexp(value, &exponent);
  if(mantissa == 0)
    return DBL_MIN;

  mantissa += DBL_EPSILON/2.0f;
  value = ldexp(mantissa, exponent);
  return value;
}

对于它的价值,标准++增量停止运行的值是9,007,199,254,740,992。

这可能不是你想要的,但你仍然可以找到 numeric_limits 正在使用中。特别是成员min()和epsilon()。

我不相信像mydouble + numeric_limits :: epsilon()这样的东西会做你想要的,除非mydouble已经接近epsilon了。如果是,那么你很幸运。

我在一段时间后发现了这段代码,也许它可以帮助你确定最小的你可以将它推高,然后再增加该值。不幸的是我不记得这段代码的参考资料:

#include <stdio.h>

int main()
{
    /* two numbers to work with */
    double number1, number2;    // result of calculation
    double result;
    int counter;        // loop counter and accuracy check

    number1 = 1.0;
    number2 = 1.0;
    counter = 0;

    while (number1 + number2 != number1) {
        ++counter;
        number2 = number2 / 10;
    }
    printf("%2d digits accuracy in calculations\n", counter);

    number2 = 1.0;
    counter = 0;

    while (1) {
        result = number1 + number2;
        if (result == number1)
            break;
        ++counter;
        number2 = number2 / 10.0;
    }

    printf("%2d digits accuracy in storage\n", counter );

    return (0);
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top