Java: реализация простого уравнения - PullRequest
2 голосов
/ 29 ноября 2009

Я хочу реализовать простое уравнение:

i, j = -Q ± √ (Q 2 -4PR) / 2P

Для этого у меня есть следующий код (примечание: P = 10. Q = 7. R = 10):

    //Q*Q – 4PR = -351 mod 11 = -10 mod 11 = 1, √1 = 1
    double test = Math.sqrt(modulo(((Q*Q) - ((4*P)*R))));

    // Works, but why *-10 needed?
    i = (int)(((-Q+test)/(P*2))*-10);    // i = 3
    j = (int)(((-Q-test)/(P*2))*-10);    // j = 4

Проще говоря, test берет первую часть уравнения и преобразовывает ее в ненулевое целое число в диапазоне от 0 до 11, затем записываются i и j. i и j возвращают правильное число, но по некоторым причинам * -10 необходимо, чтобы получить их правильно (число, которое я угадал, чтобы получить правильные значения).

Если возможно, я бы хотел найти лучший способ выполнения вышеприведенного уравнения, потому что мой способ сделать это кажется неправильным и просто работает. Я хотел бы сделать это, как предлагает уравнение, а не взломать его на работу.

Ответы [ 5 ]

6 голосов
/ 29 ноября 2009

Квадратичное уравнение чаще выражается через a, b и c. Чтобы удовлетворить топор 2 + bx + c = 0, вы получите (-b +/- sqrt(b^2-4ac)) / 2a в качестве ответов.

Я думаю, что ваша основная проблема в том, что вы по какой-то причине используете по модулю вместо получения квадратного корня. Коэффициент -10 - это просто коэффициент выдумки, который подходит для вашего теста.

У вас должно быть что-то вроде этого:

public static void findRoots(double a, double b, double c)
{
    if (b * b < 4 * a * c)
    {
        throw new IllegalArgumentException("Equation has no roots");
    }

    double tmp = Math.sqrt(b * b - 4 * a * c);
    double firstRoot = (-b + tmp) / (2 * a);
    double secondRoot = (-b - tmp) / (2 * a);
    System.out.println("Roots: " + firstRoot + ", " + secondRoot);
}

РЕДАКТИРОВАТЬ: Ваш метод modulo в настоящее время собирается хронически довольно рекурсивно. Попробуйте вместо этого:

public static int modulo(int x)
{
    return ((x % 11) + 11) % 11;
}

В основном результат первого % 11 будет в диапазоне [-10, 10] - поэтому после добавления еще 11 и взятия % 11 снова все будет правильно. Нет необходимости возвращаться.

На данный момент нет особых причин использовать его как отдельный метод, поэтому вы можете использовать:

public static void findRoots(double a, double b, double c)
{       
    int squareMod11 = (((b * b - 4 * a * c) % 11) + 11) % 11;
    double tmp = Math.sqrt(squareMod11);
    double firstRoot = (-b + tmp) / (2 * a);
    double secondRoot = (-b - tmp) / (2 * a);
    System.out.println("Roots: " + firstRoot + ", " + secondRoot);
}
1 голос
/ 29 ноября 2009

используйте Math.sqrt для квадратного корня. Почему вы бросили я и J в Ints? Это уравнение, дающее вам корни квадратной функции, поэтому i и j могут быть любыми комплексными числами. Вы должны ограничить дискриминант только положительными значениями для реальных (двойных) корней, в противном случае используйте комплексные числа.


double test = Q*Q - 4*P*R;
if(Q < 0) throw new Exception("negative discriminant!");
else {
    test = Math.sqrt(test);
    double i = (-Q + test) / 2*P;
    double i = (-Q - test) / 2*P;
}
1 голос
/ 29 ноября 2009

Вам нужно взять квадратный корень.Обратите внимание, что Q ^ 2-4PR дает отрицательное число, и, следовательно, вам придется обрабатывать комплексные числа (или ограничить ввод, чтобы избежать этого сценария). Apache Math может помочь вам здесь.

0 голосов
/ 29 ноября 2009

Как отмечают другие, ваше использование мода даже не неправильно. Почему ты так сочиняешь математику?

Хорошо известно, что наивное решение квадратного уравнения может иметь проблемы, если значение b очень близко к дискриминанту.

Лучший способ сделать это предлагается в разделе 5.6 «Числовые рецепты в C ++»: если мы определим

alt text
(источник: rulesheet.com )

Тогда два корня:

alt text

и

alt text

Ваш код также должен учитывать патологические случаи (например, a = 0).

Давайте подставим ваши значения в эти формулы и посмотрим, что мы получим. Если a = 10, b = 7 и c = 10, то:

alt text
(источник: rulesheet.com )

Тогда два корня:

alt text
(источник: rulesheet.com )

и

alt text
(источник: rulesheet.com )

Я думаю, что у меня есть правильные знаки.

Если ваши вычисления доставляют вам проблемы, это, вероятно, связано с тем, что у вас есть сложные корни, которые ваш метод не может учитывать должным образом. Вам понадобится класс комплексных чисел.

0 голосов
/ 29 ноября 2009

Почему вы делаете по модулю, а не по квадратному корню? Ваш код, кажется, способ получить корни квадратного уравнения ((a ± sqrt (b ^ 2-4ac)) / 2a), поэтому код должен быть:

double delta = Q*Q-4*P*R);
if(delta < 0.0) {
  throw new Exception("no roots");
}
double d = Math.power(delta,0.5);
double r1 = (Q + d)/(2*P)
double r2 = (Q - d)/(2*P)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...