如何用最小增量(或靠近它)来改变浮点数?

我有一个double价值f ,并想要一个方法来推动它稍大(或更小),以获得一个新的价值将尽可能接近原来的,但仍严格大于(或小于)原来的。

它不一定要靠近最后一点 – 更重要的是,无论我做出什么样的改变,都会产生不同的价值,而不会回到原来的状态。

检查你的math.h文件。 如果幸运的话,你可以定义nextafternextafterf函数。 它们以便携式和平台独立的方式完成您想要的任务,并且是C99标准的一部分。

另一种方法(可能是后备解决scheme)是将你的浮点数分解为尾数和指数部分。 递增是容易的:只需在尾数中加一个即可。 如果你得到溢出,你必须通过增加你的指数来处理这个。 减量工作方式相同。

编辑 :正如在注释中指出,它只是增加在它的二进制表示的浮动。 尾数溢出会增加指数,这正是我们想要的。

简而言之,和nextafter做的一样。

这不会是完全便携式的。 你将不得不处理endianess事实,并不是所有的机器都有IEEE浮点数(好吧 – 最后一个原因更为理论)。

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

 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; } 

绝对而言,您可以添加到浮点值来创build新的不同值的最小数量取决于当前值的大小; 这将是该types的机器epsilon乘以当前的指数。

查看IEEE规范的浮点表示法。 最简单的方法是重新解释整数types的值,加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; } 

对于什么是值得的,标准++递增function的价值是9,007,199,254,740,992。

这可能不是你想要的,但是你仍然可以在使用中findnumeric_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); }