【问题标题】:How to find the numbers that satisfy (x - y * sqrt(2016.0)) / (y + sqrt(2016.0)) = 2016 using loops in C如何使用 C 中的循环找到满足 (x - y * sqrt(2016.0)) / (y + sqrt(2016.0)) = 2016 的数字
【发布时间】:2017-10-24 18:19:35
【问题描述】:

我试图找到满足子句 (x - y * √ 2016) / (y + √ 2016) = 2016 的数字。 数 x 和 y 可以是有理数。

这是我已经尝试过的:

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

int main() {
int x, y;
    for(x = 1; x < 10000; x++) {
        for(y = 1; y < 10000; y++) {
            if( (x - y * sqrt(2016.0)) / (y + sqrt(2016.0) ) == 2016) {
                printf("Numbers are: %d and %d.", x, y);
            }
        }
    }
    return 0;
}

【问题讨论】:

  • 从表面上看,似乎没有问题;究竟是什么问题?
  • 代码总体上看起来不错,但由于 sqrt(和浮点数学)并不精确,您可能需要考虑与较小的错误余量(例如 fabs((x - y * sqrt(2016.0)) / (y + sqrt(2016.0) ) - 2016) &lt; 0.000001 或其他一些任意余量)进行比较。
  • 一些观察:(1)这是浮点数,所以你不太可能得到完全匹配。相反,您需要允许误差范围,(2)如果您可以足够接近函数接近线性的根,您可以开始将搜索空间划分为区间,依次缩小范围,(3)另一个方法是使用牛顿法。无论如何,您至少需要对所涉及的数学有所了解。
  • 为什么不用数学来解决呢?每个 y ≠ −√2016 都有一个唯一的 x,这不是一个艰难的重新排列。
  • 如果这是一项真正的任务,您应该首先求解一个变量的方程,即x = 2060.9*y+90518.2。现在你可以通过简单地为 y 插入任意值来找到你的 x 和 y 对。

标签: c loops mathematical-expressions


【解决方案1】:

使用浮点数学和蛮力搜索来“解决”这个问题在概念上是个坏主意。这是因为 FP 数学舍入误差以非直观的方式传播,因此许多在数学意义上可解的方程没有(精确)FP 数的解。因此,使用 FP 数学来逼近数学方程的解本身就很困难。

我建议在编程之前简化问题。

如果这样做并且只搜索整数解,则会发现唯一的解是

x = -2016^2 = -4064256
y = -2016

为什么:只需重新排列一下即可获得

x = 2016*y + (2016 + y)*sqrt(2016)

由于 sqrt(2016) 不是整数,因此 sqrt 之前的子句中的术语必须为零。其他一切都由此而来。

如果需要非整数解,可以使用上述方法为每个 y 找到 x。它甚至列举了所有的解决方案。

因此,这表明在尝试用计算机解决数学问题之前,通常必须对数学问题进行简化(尤其是对于 FP 数学)。

编辑:如果您寻找有理数,可以应用与整数情况相同的参数。由于 sqrt(2016) 不是有理数,因此 y 也必须是 -2016。因此,对于有理情况,唯一的解决方案与整数相同,即

x = -2016^2 = -4064256
y = -2016

【讨论】:

  • 请注意,这两个值都远远超出了 OP 用于 x 和 y 的范围(它们都是负数,并且 x 的幅度远大于 OP 正在检查的最大幅度) .但从问题中并不清楚期望的结果是什么。
【解决方案2】:

这只是一条线的方程式。这是一个确切的解决方案:

x = (sqrt(2016) + 2016)*y + 2016*sqrt(2016)

对于任何 y 值,x 由上面给出。 x 截距为:

x = 2016*sqrt(2016)
y = 0

y 轴截距为:

x = 0
y = -2016*sqrt(2016)/(sqrt(2016)+2016)

【讨论】:

  • 用这种方法识别整数解并不容易
  • 好吧,他没有明确说,但xy在他的代码中被声明为'int'
  • 实际上,现在看,很明显唯一可能的整数解是根取消的整数解,这只能在 y 为 -2016 时发生,这使 x 的值为 -2016** 2.
  • 我知道 :-),正如我在回答中所写的那样。 x 也是 -2016^2 而不是 +。
  • @AndreasH。谢谢,是的,我自己发现了这一点并修正了我的评论。
【解决方案3】:

满足 (x - y * sqrt(2016.0)) / (y + sqrt(2016.0)) = 2016 的数字

@Tom Karzes开头

x = (sqrt(2016) + 2016)*y + 2016*sqrt(2016)

设 y = -2016

x = (sqrt(2016) + 2016)*-2016 + 2016*sqrt(2016)
x = 2016*-2016 = -4064256

所以 x,y = -4064256, -2016 是一个精确解。

对于数学,这是唯一的。
由于 sqrt(x) 不完全是 √x 和 double 数学的特殊性,可能还有其他解决方案可以通过 C 代码模拟。


作为像 OP 一样的 C 模拟,让我们“猜测”答案的 x,y 都是 2016 的倍数,并且可能是负数。

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

double f(int x, int y) {
  double z = (x - y * sqrt(2016.0)) / (y + sqrt(2016.0));
  z = z - 2016;
  return z * z;
}

#define M 3000
int main() {
  double best_diff = DBL_MAX;
  int best_x = 0;
  int best_y = 0;
  int x, y;
  for (x = -M; x < M; x++) {
    for (y = -M; y < M; y++) {
      double diff = f(x * 2016, y * 2016);
      if (diff < best_diff) {
        best_diff = diff;
        best_x = x;
        best_y = y;
      }
      if (diff == 0) {
        printf("Numbers are: %d and %d.\n",  best_x*2016, best_y*2016);
      }
    }
  }
  if (best_diff != 0.0) {
    printf("Numbers are: %d and %d --> %e.", best_x*2016, best_y*2016, best_diff);
  }
  return 0;
}

输出

Numbers are: -4064256 and -2016.

【讨论】:

  • 我忘了说 x, y ∈ Q(不仅仅是一个 int,但我认为它可以使用 int 数)
  • @Co_Co 帖子说“数字 x 和 y 可以是有理数。”所有整数和有限double 都是有理数。数学问题只有一个合理的解决方案 - 它恰好是一对整数..
  • @Tom Karzes 您认为答案的哪一部分令人反感?
【解决方案4】:

浮点运算的结果通常不准确。 变化:

if( (x - y * sqrt(2016.0)) / (y + sqrt(2016.0) ) == 2016) 

类似

if( fabs((x - y * sqrt(2016.0)) / (y + sqrt(2016.0) ) - 2016) < 0.00000001)

其中0.00000001 是您选择的容差。

但正如所指出的,您不希望搜索超出必要变量的域。先解决数学问题。使用 Wolfram Alpha like this 我们得到 y=(x-24192*√14)/(12*(168+√14))

【讨论】:

    猜你喜欢
    • 2015-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多