【发布时间】:2023-03-31 00:43:01
【问题描述】:
我正在尝试对一个简单的 Fraction 类进行一些分析,并且我想要一些数据来将该类型与 doubles 进行比较。
问题
知道我正在寻找一些获得两个数字之间分数密度的好方法。分数基本上是 2 个整数(例如 pair< long, long>),s 和 t 之间的密度是该范围内可表示数字的数量。并且它必须是在 O(1) 或非常快的时间内完成的精确或非常好的近似。
为了简单一点,假设我想要 s 和 t 之间的所有数字(不是分数)a/b,其中 0 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)
结果
正如我在开始时解释的那样,我试图将Fractions 与double 进行比较。这是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
【问题讨论】:
-
您的问题很可能作为本网站的题外话而被关闭。如果您希望它被视为编程问题,这就是本网站的用途,请包括MCVE。
-
我可以在 C++ 中添加一个类 Fraction,即使你可以创建一个类,但这个问题对于每个语言或代码都是通用的。它也不是编程的主题,因为我正在尝试分析在程序中的很多情况下有用的数据类型,并且答案将被编程(这就是为什么我要求在 O(1) 或合理的快速地)。另外,这就是为什么我放弃循环遍历可能的分数并使用 gcd()。如您所见,这与编程无关。
-
如果一个近似的答案是足够的,计算在
a >= s*b和a <= t*b行之间的MxM正方形部分的面积。 -
这太过分了。此外,不是面积,而是您必须计算的那个正方形中的“点”。对于 M=6,在 0 和 1 之间给出 17 而不是 13,误差为 40%。除非你想出比我更好的公式。
-
@HighPerformanceMark:某事是否与数学有关并不是适用于 Stack Overflow 的标准。是否是特定的编程问题。这是一个特定的编程问题,也涉及数学。这是一个编程问题,因为它涉及编程中出现的特定约束,包括固定宽度算术施加的界限和性能问题(OP 要求的不是产生答案的数学函数,而是算法和快速算法,最好是 O(1))。
标签: c++ algorithm math fractions