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}");
}
}
}
}