Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何正确使用Math.Pow()?_C#_Algorithm - Fatal编程技术网

C# 如何正确使用Math.Pow()?

C# 如何正确使用Math.Pow()?,c#,algorithm,C#,Algorithm,我想找到方程的所有正整数解 a^3+b^3=c^3+d^3其中a、b、c、d是1到1000之间的整数 for (int a = 1; a <= 1000; ++a) { for (int b = 1; b <= 1000; ++b) { for (int c = 1; c <= 1000; ++c) { for (int d = 1; d <= 1000; ++d) {

我想找到方程的所有正整数解
a^3+b^3=c^3+d^3
其中a、b、c、d是1到1000之间的整数

for (int a = 1; a <= 1000; ++a)
{
    for (int b = 1; b <= 1000; ++b)
    {
        for (int c = 1; c <= 1000; ++c)
        {
            for (int d = 1; d <= 1000; ++d)
            {
                if (Math.Pow(a, 3) + Math.Pow(b, 3) == Math.Pow(c, 3) + Math.Pow(d, 3))
                {
                     Console.WriteLine("{0} {1} {2} {3}", a,b,c,d);
                }
            }
      }
}
但是第二种算法产生的结果要少得多。我的代码中的错误在哪里


我尝试了
(double)1/3
,但是第二个算法仍然比第一个算法给出的结果要少你的问题是,这一行的结果是:
intd=(int)Math.Pow(Math.Pow(a,3)+Math.Pow(b,3)-Math.Pow(c,3),1/3)
可以是非整数值,它不能满足您的要求。但是通过将其转换为
int
可以获得更多的解决方案

您应该将d更改为double,然后检查d是否为介于1和1000之间的整数值:

double d = Math.Pow(Math.Pow(a, 3) + Math.Pow(b, 3) - Math.Pow(c, 3), 1.0/3.0);
double epsilon = 0.000000001;
double dint = Math.Round(d, 0);
if (dint<=d+epsilon && dint>=d-epsilon && dint>=1-epsilon && dint<=1000+epsilon)
{
   Console.WriteLine("{0} {1} {2} {3}", a,b,c,d);
}
double d=Math.Pow(Math.Pow(a,3)+Math.Pow(b,3)-Math.Pow(c,3),1.0/3.0);
双ε=0.000000001;
双力=数学圆(d,0);
如果(力=d-ε和力>=1-ε和力替换

int d = (int)Math.Pow(Math.Pow(a, 3) + Math.Pow(b, 3) - Math.Pow(c, 3), 1/3);

修正的两个错误是

  • 1/3
    计算为整数除法,结果为
    0
    。使用
    1.0/3
    强制进行浮点除法
  • 由于浮点错误,计算可能会返回
    3.9999999 4
    ,而不是
    4
    。当转换为整数时,它会被截断为
    3
    ,从而有效地删除了一个解决方案。使用
    数学。舍入(3.999999994,0)
    将其舍入为
    4.0
    ,将其转换为
    4

  • 即使是双精度,1/3也不能用任何IEEE浮点类型精确表示

    因此,您实际上并不是在计算某个值的立方根,而是将该值提高到0.333334的幂次方或稍有偏差的版本。这会引入舍入误差,导致误差系数增加

    考虑a=995、b=990、c=990的情况:第一个循环将生成与d=995的匹配,但由于舍入错误,计算将生成d=994,这与您的条件不匹配。这将很少匹配,这解释了您看到的结果


    要解决这个问题,你可以完全使用浮点运算,但这会变得很混乱,因为你必须检查范围,因为即使在那时,代表性的问题,只有在你找到一个可能合适的范围后,你才能检查整数版本。另一个解决方案是从数学的角度来处理这个问题,而不是从数学的角度这是一种蛮力,尽管这可能需要内核方法,而且会变得非常混乱。

    这些答案几乎都不对

    你的问题是:

    我的代码中的错误在哪里

    如果您使用双精度算法来解决整数问题,则说明您做错了。请不要使用
    Math.Pow
    ,尤其不要使用它来提取立方根,并期望得到准确的整数答案

    那么你应该如何解决这个问题呢

    让我们更聪明一些,不要做不必要的工作。你的程序会发现13+123=93+103,还有123+13=103+93,依此类推。如果你知道第一个,那么你就可以很容易地知道第二个

    那么我们应该做些什么来提高效率呢

    首先,
    b
    必须大于
    a
    。这样我们就不会浪费时间去计算13+123=123+13

    类似地,
    d
    必须大于
    c

    现在,我们也可以说
    c
    d
    必须介于
    a
    b
    之间,你明白为什么了吗?

    一旦我们实施了这些限制:

        for (int a = 1; a <= 1000; ++a)
            for (int b = a + 1; b <= 1000; ++b)
                for (int c = a + 1; c < b; ++c)
                    for (int d = c + 1; d < b; ++d)
                        if (a * a * a + b * b * b == c * c * c + d * d * d)
                            Console.WriteLine($"{a} {b} {c} {d}");
    
    但我们可能比这更聪明。例如:如果我们创建了一个
    字典
    ,将多维数据集映射到它们的多维数据集根呢?只有1000个!那么我们可以说:

        for (int a = 1; a <= 1000; ++a)
        {
            int a3 = a * a * a;
            for (int b = a + 1; b <= 1000; ++b)
            {
                int b3 = b * b * b;
                int sum = a3 + b3;
                for (int c = a + 1; c < b; ++c)
                {
                    int c3 = c * c * c;
                    int d3 = sum - c3;
                    if (dict.HasKey(d3))
                    {
                        d = dict[d3];
                        Console.WriteLine($"{a} {b} {c} {d}");
                    }
                }
            }
        }
    

    for(int a=1;a 1/3是0,因为您要进行整数除法。因此,
    d
    始终是1。尝试
    (double)1/3
    尝试将1/3转换为
    double
    。d不应该是int。注意舍入错误。我尝试
    (double)1/3
    但是第二个算法得到的结果仍然比第一个算法少,那么
    (double)1/3
    呢?如果在第一行将结果强制转换为int,为什么d是double?是否检查第三行?是的。也许你应该使用
    Math.Round()
    在这里。但您可以将其保留为双倍。您可以提供一个代码吗?我不知道如何解决问题。您打算如何使用它?消除错误并不容易,因此了解您计划如何使用它将有助于推荐一个可行的解决方案;修复您的代码超出了我的能力范围,因为它会ld需要两层,第一层完全用浮点近似解,第二层尝试基于浮点解确定整数解。然而,即使是提供建议也需要更多信息,因为大多数结果的形式是a+B=B+a。您的解决方案给我+24个结果,然后是第一个算法hm(n=100)这是因为在第一个算法中,d被限制为dn的解也包括在内。要获得相同数量的结果,只需排除d>n的情况。我更新了答案:)@Anatoly在我们进入这个循环之前,字典将被预先计算,您可能会在类的静态构造函数中将它设置为一个
    静态只读IReadOnlyDictionary dict;
    字典对于只读操作是线程安全的。@Anatoly:我们也从未声明过它;我假设读者可以填写o初始化包含从多维数据集到根的映射的字典。不要只是从internet上复制粘贴代码;想想它是如何工作的。@EricLippert对不起,我明白了。你的字典的复杂性是什么
        for (int a = 1; a <= 1000; ++a)
            for (int b = a + 1; b <= 1000; ++b)
                for (int c = a + 1; c < b; ++c)
                    for (int d = c + 1; d < b; ++d)
                        if (a * a * a + b * b * b == c * c * c + d * d * d)
                            Console.WriteLine($"{a} {b} {c} {d}");
    
        for (int a = 1; a <= 1000; ++a)
        {
            int a3 = a * a * a;
            for (int b = a + 1; b <= 1000; ++b)
            {
                int b3 = b * b * b;
                int sum = a3 + b3;
                for (int c = a + 1; c < b; ++c)
                {
                    int c3 = c * c * c;
                    int d3 = sum - c3;
                    for (int d = c + 1; d < b; ++d)
                        if (d3 == d * d * d)
                            Console.WriteLine($"{a} {b} {c} {d}");
                }
            }
        }
    
        for (int a = 1; a <= 1000; ++a)
        {
            int a3 = a * a * a;
            for (int b = a + 1; b <= 1000; ++b)
            {
                int b3 = b * b * b;
                int sum = a3 + b3;
                for (int c = a + 1; c < b; ++c)
                {
                    int c3 = c * c * c;
                    int d3 = sum - c3;
                    if (dict.HasKey(d3))
                    {
                        d = dict[d3];
                        Console.WriteLine($"{a} {b} {c} {d}");
                    }
                }
            }
        }