【问题标题】:C language — Fermat's theory validator not working properlyC 语言 — 费马理论验证器无法正常工作
【发布时间】:2013-03-10 22:11:58
【问题描述】:

我的一切工作正常。 代码-

#include <stdio.h>
#include <math.h>

int quadtest(unsigned long long int a, unsigned long long int b, unsigned long long int c,     unsigned int n)
{
    if ((pow(a,n)+pow(b,n))==pow(c,n))
        return 1;
    else
        return 0;
}

main()
{
unsigned long long int a;
unsigned long long int b;
unsigned long long int c;
unsigned int n;

n=3;
for(n; n<50; n++)
{

//printf("\nn=%u",n);
    for(c=2; c<500; c++)
    {

        printf("\ntrying now c=%llu and n=%u",c,n);     
        for(b=2; b<500; b++)
        {
            for(a=2; a<500; a++)
            {
                quadtest(a,b,c,n);
                if (quadtest(a,b,c,n)==1)
                {   
                    printf("\n|||||||||||||||||||||||WORKS|||||||||||||||||||||||||||||||||");
                    break;
                }
                //printf("\na=%llu, n=%u b=%llu c=%llu",a,n,b,c);   

            }
        if (quadtest(a,b,c,n)==1)
        break;}

        if (quadtest(a,b,c,n)==1)
        break;
    }
    if (quadtest(a,b,c,n)==1)
    break;
}       
if (quadtest(a,b,c,n)==1)
printf("\nthe correct values are a=%llu,b=%llu,c=%llu,n=%u",a,b,c,n);
else
printf("\nfermats theory is correct");
}

从我的立场来看,我对所有内容都进行了正确编码,(我只使用了 50 和 500 范围,因此我可以在我的计算机上实际运行它,而不需要花费一天的时间)。

所以我在 Cygwin 中编译了程序(我需要使用它),大约花了 15 分钟左右,然后停在“正确的值是 a=381,b=2,c=381,n=7”这显然是不正确的。我不确定问题是什么或如何解决这个问题。我认为它与内存有关,但我仍然不确定它的修复方法是什么。

【问题讨论】:

  • 这就是我的想法,我不确定我的范围是什么来解决这个问题。我正在考虑将 b
  • @Alex 问题是pow() 对不精确的浮点数进行操作。使用重复乘法实现您自己的幂函数,它会起作用。
  • @Alex 使用unsigned long long,除了浮点值精度有限的问题之外,您很快就会溢出。如果你想运行正确的蛮力,你需要 bignums。

标签: c memory cygwin nested-loops


【解决方案1】:

由于您正在处理双打(pow() 返回双打), 最好使用EPSILON 来比较它们,如下所示。 你创建了一个“小”双(例如double EPSILON = 0.001) 并通过计算两个变量之间的差异来比较双精度数。

double a,b;
if(abs(a - b)) < EPSILON){
     /* your code here..
}

使用abs() 函数很重要,因此您不必 担心(a &gt; b) || (b &lt; a)

为了获得更好的结果,您可以选择较小的EPSILON

写这个:

if ((pow(a, n) + pow(b, n) - pow(c, n)) < EPSILON) {
    return 1;

【讨论】:

    【解决方案2】:

    pow() 接受双参数并返回双精度值。 double 的精度有限(通常使用 64 位)。存在一个双 x 使得 (x + 1.0) == x。这基本上就是您遇到的问题,因为 381**7 是一个非常大的整数。

    要正确进行此类计算,您需要一种方法来对大整数进行精确数学运算。您需要的通常称为“bignum”库。 GMP 就是其中之一,您可能需要检查一下。

    【讨论】:

    • 我可以将 a、b、c 的限制更改为其他值吗?老师从来没有教过bignum,所以我很确定他不希望我们用它来做这个。让我自己的幂函数起作用吗?
    • 如果这是作业,有没有可能老师只是想让你明白C中的类型精度有限,为什么明显的解决方案会失败?在 C 中,除非您推出自己的 bignum 库,否则您将在编写自己的幂函数时遇到问题。如果你坚持使用整数类型,你会遇到另一种问题——溢出。不存在满足 (n+1) == n 的 n,但存在满足 (n+1) 的 n
    • 好吧,它的功课,但它不理解数据类型的精度有限。不幸的是,我不太确定 bignum 是什么。
    • 您需要在 C 中执行此操作吗?其他一些语言(例如 Python)内置了对精确表示大整数的支持。只要您使用诸如 C 之类的语言,您就需要额外的代码来处理这些整数。这就是您在 bignum(大数字)库中可以找到的内容。如果您的老师根本没有提到这些问题,我认为您的老师不太可能希望您使用其中之一,但值得注意。
    • 抱歉,没有注意到您评论的第一句话。如果您自己选择了这些范围,那么您的老师可能根本没想到您会处理这么大的数字。请特别注意,50 的指数很大。您将无法在 unsigned long long 中表示 3**50。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多