找到等于实数分数的自然数分数
Finding a natural number fraction equal to a real number fraction
这更像是一个数学问题,但我认为这是正确的提问地点,它可能对某人有用。
以下是问题所要求的:
给定两个实数(rA 和 rB),找到最小的两个自然数(nA 和 nB),以便
rA/rB = nA/nB
对于那些没有正确理解的人来说,问题是要求一个等于某个给定实数的不可约分数。
当它变成一个精度问题并且需要花费大量时间才能找到这些数字(例如:rA = 665.32
和rB = 875.1
)时,我的问题就出现了,我什至不知道是否有这样的自然数组合来匹配问题。
我还实现了一点KeyPress
,以便您仍然可以检查nA
和nB
获得了多少,而无需使控制台已满。
我想出的最有效的方法是:
#include <iostream>
#include <windows.h> // just for GetAsyncKeyState()
int main()
{
/** The two natural numbers*/
unsigned long long nA=1;
unsigned long long nB=1;
/** The two real numbers*/
double rA;
double rB;
std::cin >> rA >> rB;
bool bPairFound = false;
/** The maximum of which nA or nB could go. */
/** If the value is set to 0, the algorithm will stop when nA or nB overflows */
#define NUMBER_LIMIT 0x0
if ((double) nA / nB == rA / rB) bPairFound = true;
while(bPairFound == false)
{
if ((double) nA / nB > rA / rB) nB++;
if ((double) nA / nB < rA / rB) nA++;
if ((double) nA / nB == rA / rB) bPairFound = true;
/** A little keyPress that will show you how much nA and nB got. */
/** Press space while the program is running. */
if (GetAsyncKeyState(VK_SPACE) & 0x8000)
std::cout << "nA: "<<nA<<" nB: " << nB << " ---> "<< (double) nA / nB << " " << rA / rB << std::endl;
if (nA <= NUMBER_LIMIT || nB <= NUMBER_LIMIT) break;
}
if (bPairFound == false) std::cout << "No pair could be found in the set limit." << std::endl;
if (bPairFound == true) std::cout << "nA: "<<nA<<" nB: " << nB << std::endl;
return 0;
}
我的问题是:
我能让这个算法更有效吗?
如何将比较
precision
设置为 6 位数字?有没有办法从一开始就确定
unsigned long long
范围内是否有这样的货币对?
编辑:这里有一些需要太多时间来解决或无法解决的例子。
rA = 1426.33
rB = 12.7
rA = 764342.33
rB = 98.02001
rA = 1.0001
rB = 1.010001
除了精度问题(a)之外,你可以通过确保数字是整数,然后将它们除以最大公约数来最有效地做到这一点。
具体来说,伪代码,例如:
tA = rA
tB = rB
while tA != int(tA) or tB != int(tB):
tA = tA * 10
tB = tB * 10
gcd = calcGcd(tA, tB)
nA = tA / gcd
nB = tB / gcd
GCD实现应该很容易在Stack Overflow上找到。
事实上,这是我之前准备的:-)
(a)精度问题可以通过使用任意精度的算术库(如MPIR)来解决。
我相信这会更有效率。
while(bPairFound == false)
{
double left=(double)nA*rB;
double right=(double)nB*rA;
if(left>right){
double quotient=left/right;
unsigned long long prevB=nB;
nB*=quotient;
if(prevB==nB){
nB++;
}
}else if(right>left){
int quotient=right/left;
unsigned long long prevA=nA;
nA*=quotient;
if(prevA==nA){
nA++;
}
}else{
bPairFound = true;
}
/** A little keyPress that will show you how much nA and nB got. */
/** Press space while the program is running. */
if (GetAsyncKeyState(VK_SPACE) & 0x8000)
std::cout << "nA: "<<nA<<" nB: " << nB << " ---> "<< (double) nA / nB << " " << rA / rB << std::endl;
if (nA <= NUMBER_LIMIT || nB <= NUMBER_LIMIT) break;
}
由于您正在按商增加数字,因此您将在早期过程中跳过相当多的步骤。 此外,此实现具有更多的乘法和更少的除法。由于乘法的收费较低,因此此方法将更有效。
我希望这有所帮助。
编辑 1: 我找到了一种提高系统精度的方法
double left=(double)nA*rB;
double right=(double)nB*rA;
double quotient=left/right;
unsigned long long test;
if(quotient>=1){
test=quotient*1000000;
}else{
test=100000/quotient;
}
if(test==1000000){
bPairFound = true;
}else if(left>right){
unsigned long long prevB=nB;
nB*=quotient;
if(prevB==nB){
nB++;
}
}else if(right>left){
unsigned long long prevA=nA;
nA*=1/quotient;
if(prevA==nA){
nA++;
}
}
- 如何从复数返回实数
- 找到等于实数分数的自然数分数
- 是否可以保证输入<Type>实数时复杂对象的虚部设置为零?
- 自然数除数的颜色
- 如何在不重新发明轮子的情况下为自定义类型生成均匀分布的随机实数
- C++ 如何在单独的函数中验证用户输入的实数
- 一个更好的实数生成器
- C++,构造一个读取两个实数和一个字符的程序
- 在原点附近对实数进行舍入会导致旋转伪影
- 自然数(递归)的设定理论定义
- 前五个自然数的总和
- 根据队列内容(if 语句)确定数字是实数还是整数
- 我可以在 c++ 中使用哪些正则表达式来解析分隔符、运算符、标识符和实数?
- 在 c++ 中将八进制数变成实数
- 使用boost::random库获取整数随机值而不是实数
- C/C++ 中是否有自然数的基本类型
- 前 20 个自然数的 LCM
- .读取实数,直到找到 10 个正值.写出 10 个正数的总和
- 随机实数在 [0.1[ 使用梅森扭曲
- 返回对 C++11 中复数的实数或 IMAG 值的引用的函数