2个给定数字之间的分数密度

时间:2018-01-13 23:31:55

标签: c++ algorithm math fractions

我正在尝试对一个简单的Fraction类进行一些分析,我想要一些数据来将该类型与doubles进行比较。

问题

知道我正在寻找一些好的方法来获得2个数字之间的分数密度。分数基本上是2个整数(例如pair< long, long>),st之间的密度是该范围内可表示数字的数量。它需要是在O(1)或非常快的情况下完成的精确或非常好的近似。

为了使它更简单,假设我想要s和t之间的所有数字(不是分数)a / b,其中0 <= s&lt; = a / b&lt; t <= M,并且0 <= a,b <= M(b> 0,a和b是整数)

实施例

如果我的分数是一个只计数为6(M = 6)的数据类型,而我希望密度在0和1之间,则答案为12.这些数字是:

0, 1/6, 1/5, 1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4, 4/5, 5/6.

我的想法

一种非常天真的方法是循环所有可能的分数,并计算那些不能简化的分数。类似的东西:

long fractionsIn(double s, double t){
    long density = 0;
    long M = LONG_MAX;
    for(int d = 1; d < floor(M/t); d++){
        for(int n = ceil(d*s); n < M; n++){
            if( gcd(n,d) == 1 )
                density++;
        }
    }
    return density;
}

但是gcd()非常慢,所以它不起作用。我也尝试做一些数学但我无法做任何好事。

解决方案

感谢@ m69回答,我为Fraction = pair<Long,Long>创建了此代码:

//this should give the density of fractions between first and last, or less.
double fractionsIn(unsigned long long first, unsigned long long last){
    double pi = 3.141592653589793238462643383279502884;
    double max = LONG_MAX;  //i can't use LONG_MAX directly
    double zeroToOne = max/pi * max/pi * 3; // = approx. amount of numbers in Farey's secuence of order LONG_MAX. 
    double res = 0;

    if(first == 0){
        res = zeroToOne;
        first++;
    }

    for(double i = first; i < last; i++){
        res += zeroToOne/(i * i+1);
        if(i == i+1)
            i = nextafter(i+1, last);   //if this happens, i might not count some fractions, but i have no other choice
    }

    return floor(res);
}

主要变化是nextafter,这对于大数字(1e17)非常重要

结果

正如我在开始时解释的那样,我试图将Fractionsdouble进行比较。以下是Fraction = pair<Long,Long>(以及here如何获得双打密度的结果):

Density between 0,1:                | 1,2              | 1e6,1e6+1   | 1e14,1e14+1 | 1e15-1,1e15 | 1e17-10,1e17 | 1e19-10000,1e19 | 1e19-1000,1e19
Doubles:        4607182418800017408 | 4503599627370496 | 8589934592  | 64          | 8           | 1            | 5               | 0
Fraction:       2.58584e+37         | 1.29292e+37      | 2.58584e+25 | 2.58584e+09 | 2.58584e+07 | 2585         | 1               | 0

1 个答案:

答案 0 :(得分:2)

这与:(Sum of phi(k))完全相同,其中m <= k <= M其中phi(k)Euler Totient Functionphi(0) = 1(由问题定义)。这笔款项没有已知的封闭表格。但是,wiki链接中提到了许多已知的优化。这被称为Wolfram中的Totient Summatory Function。该网站还链接到该系列:A002088并提供一些渐近近似值。

原因是:考虑{1/M, 2/M, ...., (M-1)/M, M/M}形式的值的数量。所有那些可以减少到较小值的分数将不会计入phi(M),因为它们不是相对素数。它们将出现在另一个人的总和中。

例如,phi(6) = 12您有1 + phi(6),因为您还会计算0