LINUX.ORG.RU

задачка на решение квадратного уравнения

 ,


0

1

Подскажите ,пожалуйста, как можно упростить мой код:

from math import sqrt


def get_roots(a, b, c):
    # a=0 makes the function linear, not quadratic.
    if a == 0:
        return None, None
    else:
        discriminant = b ** 2 - 4 * a * c
        # The square root is extracted only from a nonnegative number.
        if discriminant < 0:
            return None, None
        # If discriminant is 0, then roots of the quadratic equation 1.
        elif discriminant == 0:
            root1 = (-b - sqrt(discriminant)) / (2 * a)
            return root1, None
        # If discriminant > 0, then roots of the quadratic equation 2.
        else:
            root1 = (-b - sqrt(discriminant)) / (2 * a)
            root2 = (-b + sqrt(discriminant)) / (2 * a)
            return root1, root2

Код работает верно ,но нужно обойтись без вложенных if-ов и без использования root1 два раза.

Пробую сделать двумя функциями, но возникает ошибка:

TypeError: 'NoneType' object is not iterable
def get_roots(a, b, c):
    discriminant = b ** 2 - 4 * a * c
    if discriminant < 0:
        return None, None
    else:
        roots(a, b, discriminant)

def roots(a, b, d):
    root1 = (-b - sqrt(d)) / (2 * a)
    root2 = (-b + sqrt(d)) / (2 * a)
    if d == 0:
        return root1, None
    else:
        return root1, root2
Ответ на: комментарий от Sahas

Случай a=b=0 вообще не отлавливается.

а не нужно: оно не «квадратное»

по сабжу: 1) local D = .. на мой взгляд лучше читается; 2) может опустить случай D == 0: просто двойная кратность; 3) a == 2 - если с плавающей точкой, то так не проверяют

anonymous ()
from math import sqrt


def get_roots(a, b, c):
    # a=0 makes the function linear, not quadratic.
    if a == 0:
        return None, None

    discriminant = b ** 2 - 4 * a * c
    # The square root is extracted only from a nonnegative number.
    if discriminant < 0:
        return None, None

    root1 = (-b - sqrt(discriminant)) / (2 * a)
    root2 = None

    if discriminant > 0:
        root2 = (-b + sqrt(discriminant)) / (2 * a)

    return root1, root2

И я согласен с товарищем Sahas.

JaneDoe ()

Если только вещественные корни и без проверки, что уравнение квадратное:

def roots(a, b, c):
    d = b ** 2 - 4 * a * c

    return ((-b + sqrt(d)) / (2 * a),
            (-b - sqrt(d)) / (2 * a)) if d >= 0 else (None, None)
vvn_black ★★★ ()

При discriminant == 0, будет кратный корень. Один и тот же корень два раза. Поэтому неправильно возвращать (root1, None), как будто он единственный.

renjumin ★★★ ()
Ответ на: комментарий от vvn_black

А почему этот фрагмент тест пройти не может? А кусок с кучей if-ов проходит.

import unittest

from quadratic_equation import get_roots


class QuadraticEquationTestCase(unittest.TestCase):
    def test_solves_real_roots(self):
        root1, root2 = get_roots(1, -2, 1)
        self.assertEqual(root1, 1)

    def test_first_root_less_than_second(self):
        root1, root2 = get_roots(1, 2, -3)
        self.assertEqual(root1, -3)
        self.assertEqual(root2, 1)

    def test_second_root_is_none_if_one_solution(self):
        root1, root2 = get_roots(1, -2, 1)
        self.assertIsNotNone(root1)
        self.assertIsNone(root2)

    def test_returns_none_for_complex_solution(self):
        root1, root2 = get_roots(1, 2, 3)
        self.assertIsNone(root1)
        self.assertIsNone(root2)


if __name__ == '__main__':
    unittest.main()

Ошибки тестов:

FAIL: test_first_root_less_than_second (__main__.QuadraticEquationTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests.py", line 13, in test_first_root_less_than_second
    self.assertEqual(root1, -3)
AssertionError: 1.0 != -3

======================================================================
FAIL: test_second_root_is_none_if_one_solution (__main__.QuadraticEquationTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests.py", line 19, in test_second_root_is_none_if_one_solution
    self.assertIsNone(root2)
AssertionError: 1.0 is not None

PavelShturm ()
Ответ на: комментарий от PavelShturm

AssertionError: 1.0 != -3

и

AssertionError: 1.0 is not None

Порядок в котором корни считаются отличается. И в моем примере при d == 0 возвращаются два одинаковых корня.

vvn_black ★★★ ()
Последнее исправление: vvn_black (всего исправлений: 1)
Ответ на: комментарий от vvn_black
def get_roots(a, b, c):
    discriminant = b ** 2 - 4 * a * c
    if discriminant >= 0:
        return ((-b - sqrt(discriminant)) / (2 * a),
                (-b + sqrt(discriminant)) / (2 * a))
    else:
        return None, None

Тест одну ошибку выдает:

Traceback (most recent call last):
  File "tests.py", line 19, in test_second_root_is_none_if_one_solution
    self.assertIsNone(root2)
AssertionError: 1.0 is not None

Из-за того что при дискр. равном нулю - два одинаковых корня, а тест считает их одним?

PavelShturm ()
Ответ на: комментарий от slamd64

с кратными сначала пусть разберется. Возвращать при Д=0 `return root1, None` нелогично. Надо `return root1, root1`. Потому как понятие «кратные корни» ввели как раз в таком случае, когда подразумевается пара корней в соответствии со степенью квадратного уравнения.

PtiCa ★★★★★ ()
Ответ на: комментарий от PavelShturm

Ну ты уже ведь не в пятом классе, где «детишечки, квадратный корень из отрицательных низя». И кто сказал что корни обязаны быть целыми?

>>> 25**0.49
4.841618928628149
А если вот так?
>>> (25 + 3j)**0.49
(4.850291034420112+0.28416433222512705j)

I-Love-Microsoft ★★★★★ ()
Ответ на: комментарий от I-Love-Microsoft

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

from math import sqrt


def get_roots(a, b, c):
    discriminant = b ** 2 - 4 * a * c
    if discriminant < 0:
        return None, None
    else:
        root1 = (-b - sqrt(discriminant)) / (2 * a)
        root2 = (-b + sqrt(discriminant)) / (2 * a)
        return root1, root2 if discriminant > 0 else None

Этот код прошел те тесты, но странно ,что не выдал ошибку на else None в конце.

PavelShturm ()