给定 (a, b) 计算 k 的最大值,使得 a^{1/k} 和 b^{1/k} 是整数
Given (a, b) compute the maximum value of k such that a^{1/k} and b^{1/k} are whole numbers
我正在编写一个程序,试图找到 k> 1 的最小值,使得 a 和 b 的第 k 个根(都给定)等于整数。
这是我的代码片段,为了澄清,我已经对其进行了注释。
int main()
{
// Declare the variables a and b.
double a;
double b;
// Read in variables a and b.
while (cin >> a >> b) {
int k = 2;
// We require the kth root of a and b to both be whole numbers.
// "while a^{1/k} and b^{1/k} are not both whole numbers..."
while ((fmod(pow(a, 1.0/k), 1) != 1.0) || (fmod(pow(b, 1.0/k), 1) != 0)) {
k++;
}
几乎,我读了 (a, b),我从 k = 2 开始并递增 k,直到 a 和 b 的第 k 个根都与 0 mod 1 全等(这意味着它们可以被 1 整除,因此是整数)。
但是,循环无限运行。我尝试过研究,我认为这可能与精度错误有关;但是,我不太确定。
我尝试过的另一种方法是更改循环条件以检查 a^{1/k} 的下限是否等于 a^{1/k} 本身。但同样,这可能是由于精度误差,这是无限运行的。
有谁知道我该如何解决这个问题?
编辑:例如,当(a,b)= (216,125)时,我希望k = 3,因为216^(1/3)和125^(1/3)都是整数(即5和6)。
这不是一个编程问题,而是一个数学问题:
如果
a
是实数,k
是正整数,如果a^(1./k)
是整数,则a
是整数。(否则目的是玩弄近似误差)
因此,最快的方法可能是首先检查a
和b
是否是整数,然后进行素数分解,使得 a=p 0 e0*p1e1* ...,其中pi是不同的素数。
请注意,要使1/k 成为整数,每个 ei也必须能被 k 整除。换句话说,k 必须是 ei的公约数。如果 b1/k是整数,则 b 的素幂也必须如此。
因此,最大的k
是a
和b
的所有ei的最大公约数。
使用您的方法,您将遇到大量问题。所有 IIEEE 754 二进制 64 浮点数(x86 上的双精度情况)都有 53 个有效位。这意味着所有大于 253的双精度都是整数。
函数pow(x,1./k)
将为两个不同的x
产生相同的值,因此使用您的方法,您必须有错误的答案,例如数字 55*290和 35*2120完全可以用双精度表示。算法的结果是k=5
.您可能会在这些数字中找到k
的值,但您也会找到 55*290-249和 35*2120的k=5
,因为 pow(55*290-249,1./5)==pow(55*290)。在这里演示
另一方面,由于只有 53 个有效位,双精度的素数分解是微不足道的。
浮点数不是数学实数。计算是"近似的"。请参阅 http://floating-point-gui.de/
你可以用类似fabs(fmod(pow(a, 1.0/k), 1) - 1.0) > 0.0000001
的东西替换测试fmod(pow(a, 1.0/k), 1) != 1.0
(并使用各种这样的而不是0.0000001
;另请参阅std::numeric_limits::epsilon,但要谨慎使用它,因为pow
可能会在其计算中给出一些错误,并且1.0/k
也会注入不精确性 - 细节非常复杂,深入研究IEEE754规范)。
当然,你可以(并且可能应该)定义你的bool almost_equal(double x, double y)
函数(并使用它而不是==
,并使用它的否定而不是!=
)。
根据经验,切勿测试浮点数的相等性(即==
),但请考虑它们之间足够小的距离;也就是说,将像x == y
(分别为x != y
)这样的测试替换为类似fabs(x-y) < EPSILON
(分别为fabs(x-y) > EPSILON
),其中EPSILON
是一个小的正数,因此测试一个小的 L1距离(对于相等,以及足够大的距离来表示不相等)。
并避免整数问题中的浮点数。
实际上,预测或估计浮点精度是非常困难的。您可能需要考虑像 CADNA 这样的工具。我的同事Franck Védrine是静态程序分析仪估计数值误差的专家(例如,参见他在TERATEC 2017关于Fluctuat的演讲)。这是一个困难的研究课题,另见D.Monniaux的论文《验证浮点计算的陷阱》等。
浮点错误在某些情况下确实造成了人命损失(或损失数十亿美元)。搜索网络以获取详细信息。在某些情况下,计算数字的所有数字都是错误的(因为错误可能会累积,最终结果是通过组合数千个操作获得的)!与混沌理论有一些间接关系,因为许多程序可能有一些数值不稳定。
正如其他人所提到的,比较相等的浮点值是有问题的。如果您找到一种直接使用整数的方法,则可以避免此问题。一种方法是将整数提高到k
次幂,而不是取第k
个根。细节留给读者作为练习。
- 整数溢出,最大值为 pow(10,19)
- 递归函数,用于查找 2 个整数之间的最大值
- 我无法显示包含整数最大值的索引. 但我可以显示数组中整数的最高值
- 如何在 c++ 中解析包含整数的字符串并检查是否大于最大值
- 是`-1`正确地用作无符号整数的最大值
- 需要帮助显示用户输入的整数的最小/最大值
- 给定一个数组和整数k,在大小为k的每个子数组中找到最大值
- 给定 (a, b) 计算 k 的最大值,使得 a^{1/k} 和 b^{1/k} 是整数
- 给定一个整数数组和一个数k,计算长度为k的每个子数组的最大值
- C++按位运算,最大值为 12 位整数
- 如何显示从文件中读取的整数的最小值和最大值
- 所有整数对 a、b(l ≤ a ≤ b ≤ r)的 xor b 的最大值
- 如何找到给定方程 ax + by = c 的最大值 (x+y),其中 a,b,c 是常数,x , y >= 0 并且都是整数?
- 模板函数如何获得整数或字符的最大值
- 有符号整数类型的最大值
- 无符号整数的最大值
- 无符号整数的快速无分支最大值
- 如何找到未知整数类型的最大值
- 统计“用户输入”中输入的奇数、偶数、最大值和整数的总数
- 如何在数组中找到整数的ADT堆栈中的最大值