从(long)double转换为size_t

时间:2018-12-19 16:14:43

标签: c++ casting floating-point type-conversion precision

我正在尝试尽可能高效地实现Eratosthenes筛网。我想将素数数组的长度设置为的上限 pi(n) < 1.25506n / ln n 但我不确定如何进行转换以安全地进行转换,也不确定哪种类型的组合最适合此操作。

我的列表的最大长度将受到数组的最大大小的限制。

我的猜测是,理想的组合取决于size_t在内部的实现方式及其上限。

我希望得到尽可能接近的结果 ceil( 1.25506n / ln n),而且数字越来越小。

有人建议如何做吗?

1 个答案:

答案 0 :(得分:0)

这是一种实现方法:

#include <cstddef>
#include <cfloat>
#include <cmath>

std::size_t piUpperBound(std::size_t n) {
    double x = n;
    double num = nextafter(x, DBL_MAX);

    x = log(x);
    double den = nextafter(x, -DBL_MAX);

    double result = num/den;
    result = nextafter(1.25506, DBL_MAX)*nextafter(result, DBL_MAX);
    result = nextafter(result, DBL_MAX);

    return ceil(result);
}

此代码假定log最多有1个ulp错误。

基本思想是使用nextafter,它为我们提供了下一个可能的浮点数。每次操作后,我都叫nextafter,以某种方式修改数字,使结果表达式始终保持上限。

如果我们想,可以创建一个更好的界限,即除法,乘法运算是正确舍入的(对于IEEE-754是正确的),并且我们可以代替nextafter来调整舍入模式(始终向上或向下舍入) )。

注意:

  • ceil用于原始表达式可能是保守的。例如,如果pi(...)= 12.2,则最多有12个质数,而不是13。
  • 该公式非常保守,如您所见here。因此,实际上,不需要整个浮点业务。即使代码计算错误,它仍然是一个较大的上限。