我正在尝试尽可能高效地实现Eratosthenes筛网。我想将素数数组的长度设置为的上限
pi(n) < 1.25506n / ln n
但我不确定如何进行转换以安全地进行转换,也不确定哪种类型的组合最适合此操作。
我的列表的最大长度将受到数组的最大大小的限制。
我的猜测是,理想的组合取决于size_t在内部的实现方式及其上限。
我希望得到尽可能接近的结果
ceil( 1.25506n / ln n)
,而且数字越来越小。
有人建议如何做吗?
答案 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。