Предложите разные подходы к решению квадратного уравнения ax^2 + bx + c = 0 в случае малых значений b по сравнению с a и c (учёт потерь точности при численных вычислениях); обсудите стабильность формул
Кратко — набор рабочих приёмов и замечаний о численной устойчивости при ax2+bx+c=0ax^2+bx+c=0ax2+bx+c=0 и малом ∣b∣|b|∣b∣ по сравнению с ∣a∣|a|∣a∣ и ∣c∣|c|∣c∣. 1) Стандартная формула (опасность вычитания) - Формула: x1,2=−b±b2−4ac2a.x_{1,2}=\frac{-b\pm\sqrt{b^2-4ac}}{2a}.x1,2=2a−b±b2−4ac.
- Проблема: если ∣b∣≪∣4ac∣|b|\ll\sqrt{|4ac|}∣b∣≪∣4ac∣ и корни имеют противоположные знаки по модулю, то при вычислении того корня, где знак в числителе приводит к вычитанию схожих по величине чисел, возникает катастрофическое вычитание и потеря значащих цифр. 2) Устойчивое вычисление через вспомогательную величину qqq
- Вычислить дискриминант D=b2−4acD=b^2-4acD=b2−4ac и D\sqrt{D}D (для комплексных корней — комплексный корень). - Возьмём sign(b)\operatorname{sign}(b)sign(b) как 111 если b≥0b\ge0b≥0, иначе −1-1−1. Затем: q=−12(b+sign(b)D).q=-\tfrac12\bigl(b+\operatorname{sign}(b)\sqrt{D}\bigr).q=−21(b+sign(b)D).
- Тогда корни: x1=qa,x2=cq.x_1=\frac{q}{a},\qquad x_2=\frac{c}{q}.x1=aq,x2=qc.
- Почему лучше: выбор знака в qqq делает сумму в скобках большой по модулю, избегая вычитания близких чисел; второй корень получается через деление по произведению (устойчиво). 3) Использование Виетовых соотношений (если один корень вычислен точно) - Если точно получили корень с большим модулем xbigx_{\text{big}}xbig, второй корень вычисляется как xother=ca xbig.x_{\text{other}}=\frac{c}{a\,x_{\text{big}}}.xother=axbigc.
- Это часто даёт высокую относительную точность для второго корня, когда прямая формула даёт погрешность. 4) Балансировка (масштабирование переменной) - Сделать уравнение моническим: x2+bax+ca=0.x^2+\frac{b}{a}x+\frac{c}{a}=0.x2+abx+ac=0.
- Масштабировать x=y⋅sx=y\cdot sx=y⋅s с s=∣ca∣s=\sqrt{\left|\frac{c}{a}\right|}s=ac (чтобы константа стала ±1\pm1±1). Тогда коэффициенты становятся более сбалансированными и уменьшается риск вычитания при вычислении корней. После решения для yyy перевести обратно x=syx=syx=sy. 5) Асимптотические/разложенческие приближения при очень малом bbb
- Для b→0b\to0b→0 корни стремятся к ±−ca\pm\sqrt{-\frac{c}{a}}±−ac (если ac<0ac<0ac<0 — действительные) с малой поправкой. Можно использовать разложение в ряд по bbb для начального приближения и затем уточнить (см. пункт 6). 6) Итеративное уточнение (Ньютон) для повышения точности - Если получили приближённый корень x(0)x^{(0)}x(0), одну итерацию Ньютона: x(1)=x(0)−ax(0)2+bx(0)+c2ax(0)+bx^{(1)}=x^{(0)}-\frac{ax^{(0)2}+bx^{(0)}+c}{2ax^{(0)}+b}x(1)=x(0)−2ax(0)+bax(0)2+bx(0)+c
- Одна-две итерации часто восстанавливают полную машинную точность (если начальное приближение достаточно близко). 7) Комплексные корни - Если D<0D<0D<0, вычисляйте D\sqrt{D}D как комплексное число и применяйте тот же устойчивый приём с qqq. Для вещественной и мнимой частей лучше отделять: Re(x)=−b2a,Im(x)=±4ac−b22∣a∣.\operatorname{Re}(x)=-\frac{b}{2a},\qquad \operatorname{Im}(x)=\pm\frac{\sqrt{4ac-b^2}}{2|a|}.Re(x)=−2ab,Im(x)=±2∣a∣4ac−b2.
- Следует избегать явного вычитания при вычислении малой реальной части; лучше получить её как −b/(2a)-b/(2a)−b/(2a). 8) Применение повышенной точности или специальных алгоритмов - Если проблема сильно плохо обусловлена (например, корни одинаковы по модулю и противоположны по знаку), единственный надёжный путь — арифметика с большей точностью (long double, quad) или использование специализированных библиотек/методов (например, алгоритмы для полиномиальных корней — Jenkins–Traub), которые дают устойчивые результаты. Краткие указания по выборам в практике - Используйте формулу с qqq и затем c/qc/qc/q — это самое простое и надёжное решение в большинстве случаев. - Если один корень получается с плохой точностью, пересчитайте второй как c/(ax1)c/(a x_1)c/(ax1). - Если нужно гарантировать абсолютную/относительную точность при сильно неустойчивых коэффициентах — повышайте точность вычислений и/или применяйте итеративное уточнение. Замечание о обусловленности - При маленьком ∣b∣|b|∣b∣ сумма корней −ba\tfrac{-b}{a}a−b мала относительно их модулей (корни почти одинаковы по модулю, противоположны по знаку), поэтому задача найти оба корня с высокой относительной точностью одновременно плохо обусловлена: обычно можно получить оба с хорошей абсолютной точностью, но только один с хорошей относительной точностью; второй лучше получать через произведение.
1) Стандартная формула (опасность вычитания)
- Формула: x1,2=−b±b2−4ac2a.x_{1,2}=\frac{-b\pm\sqrt{b^2-4ac}}{2a}.x1,2 =2a−b±b2−4ac . - Проблема: если ∣b∣≪∣4ac∣|b|\ll\sqrt{|4ac|}∣b∣≪∣4ac∣ и корни имеют противоположные знаки по модулю, то при вычислении того корня, где знак в числителе приводит к вычитанию схожих по величине чисел, возникает катастрофическое вычитание и потеря значащих цифр.
2) Устойчивое вычисление через вспомогательную величину qqq - Вычислить дискриминант D=b2−4acD=b^2-4acD=b2−4ac и D\sqrt{D}D (для комплексных корней — комплексный корень).
- Возьмём sign(b)\operatorname{sign}(b)sign(b) как 111 если b≥0b\ge0b≥0, иначе −1-1−1. Затем: q=−12(b+sign(b)D).q=-\tfrac12\bigl(b+\operatorname{sign}(b)\sqrt{D}\bigr).q=−21 (b+sign(b)D ). - Тогда корни: x1=qa,x2=cq.x_1=\frac{q}{a},\qquad x_2=\frac{c}{q}.x1 =aq ,x2 =qc . - Почему лучше: выбор знака в qqq делает сумму в скобках большой по модулю, избегая вычитания близких чисел; второй корень получается через деление по произведению (устойчиво).
3) Использование Виетовых соотношений (если один корень вычислен точно)
- Если точно получили корень с большим модулем xbigx_{\text{big}}xbig , второй корень вычисляется как xother=ca xbig.x_{\text{other}}=\frac{c}{a\,x_{\text{big}}}.xother =axbig c . - Это часто даёт высокую относительную точность для второго корня, когда прямая формула даёт погрешность.
4) Балансировка (масштабирование переменной)
- Сделать уравнение моническим: x2+bax+ca=0.x^2+\frac{b}{a}x+\frac{c}{a}=0.x2+ab x+ac =0. - Масштабировать x=y⋅sx=y\cdot sx=y⋅s с s=∣ca∣s=\sqrt{\left|\frac{c}{a}\right|}s= ac (чтобы константа стала ±1\pm1±1). Тогда коэффициенты становятся более сбалансированными и уменьшается риск вычитания при вычислении корней. После решения для yyy перевести обратно x=syx=syx=sy.
5) Асимптотические/разложенческие приближения при очень малом bbb - Для b→0b\to0b→0 корни стремятся к ±−ca\pm\sqrt{-\frac{c}{a}}±−ac (если ac<0ac<0ac<0 — действительные) с малой поправкой. Можно использовать разложение в ряд по bbb для начального приближения и затем уточнить (см. пункт 6).
6) Итеративное уточнение (Ньютон) для повышения точности
- Если получили приближённый корень x(0)x^{(0)}x(0), одну итерацию Ньютона: x(1)=x(0)−ax(0)2+bx(0)+c2ax(0)+bx^{(1)}=x^{(0)}-\frac{ax^{(0)2}+bx^{(0)}+c}{2ax^{(0)}+b}x(1)=x(0)−2ax(0)+bax(0)2+bx(0)+c - Одна-две итерации часто восстанавливают полную машинную точность (если начальное приближение достаточно близко).
7) Комплексные корни
- Если D<0D<0D<0, вычисляйте D\sqrt{D}D как комплексное число и применяйте тот же устойчивый приём с qqq. Для вещественной и мнимой частей лучше отделять: Re(x)=−b2a,Im(x)=±4ac−b22∣a∣.\operatorname{Re}(x)=-\frac{b}{2a},\qquad \operatorname{Im}(x)=\pm\frac{\sqrt{4ac-b^2}}{2|a|}.Re(x)=−2ab ,Im(x)=±2∣a∣4ac−b2 . - Следует избегать явного вычитания при вычислении малой реальной части; лучше получить её как −b/(2a)-b/(2a)−b/(2a).
8) Применение повышенной точности или специальных алгоритмов
- Если проблема сильно плохо обусловлена (например, корни одинаковы по модулю и противоположны по знаку), единственный надёжный путь — арифметика с большей точностью (long double, quad) или использование специализированных библиотек/методов (например, алгоритмы для полиномиальных корней — Jenkins–Traub), которые дают устойчивые результаты.
Краткие указания по выборам в практике
- Используйте формулу с qqq и затем c/qc/qc/q — это самое простое и надёжное решение в большинстве случаев.
- Если один корень получается с плохой точностью, пересчитайте второй как c/(ax1)c/(a x_1)c/(ax1 ).
- Если нужно гарантировать абсолютную/относительную точность при сильно неустойчивых коэффициентах — повышайте точность вычислений и/или применяйте итеративное уточнение.
Замечание о обусловленности
- При маленьком ∣b∣|b|∣b∣ сумма корней −ba\tfrac{-b}{a}a−b мала относительно их модулей (корни почти одинаковы по модулю, противоположны по знаку), поэтому задача найти оба корня с высокой относительной точностью одновременно плохо обусловлена: обычно можно получить оба с хорошей абсолютной точностью, но только один с хорошей относительной точностью; второй лучше получать через произведение.