Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

[ Миронченко ] Императивное и объектно-ориентированное програмирование на Turbo Pascal и Delphi

.pdf
Скачиваний:
69
Добавлен:
25.04.2014
Размер:
3.16 Mб
Скачать

71

Натуральное число n называется составным, если у него существуют делители, отличные от 1 и n

Пример: 39 – составное (делители – 1, 3, 13, 39).

Искать НОД чисел бывает нужно в самых различных ситуациях. Простейшая из них – сокращение дробей.

Если числа малы, то найти их НОД и НОК можно методом подбора. Но что делать, если числа достаточно велики, скажем 121353 и 2954653. Тут уже метод подбора не пройдет. Нам нужны алгоритмы, которые позволят быстро находить НОД и НОК 2-х чисел.

Рассмотрим 2 из них:

Первый алгоритм базируется на использовании следующей теоремы, которую мы примем без доказательства.

Основная теорема арифметики:

Любое натуральное число a >1 единственным образом представляется в виде

a = p1k1 p2k2 ...pnkn , где p1 < p2 < ... < pn - простые числа, а ki , i = 1, n - целые положительные числа

Теперь пусть у нас есть 2 числа a , b . По основной теореме арифметике получим разложения (называемые каноническими)

a = p1k1 p2k2 ...pnkn

b = t1s1 t2s2 ...tmsm

Множества Р={p1 , p2 ,..., pn } и Т={t1 ,t2 ,...,tm }, вообще говоря, не совпадают (т.е.

могут совпадать, а могут и нет).

 

 

 

 

 

 

 

 

 

 

Построим множество

Q = P U T

 

- множество простых чисел, которые

присутствуют в разложении хотя бы одного из чисел a , b .

Теперь разложим числа a ,

 

b по числам qi :

r

r

...q

rf

, q

 

Q , r

 

 

ki , i : ki = rj

a = q 1 q

2

 

 

 

 

=

1

2

 

f

 

j

 

j

 

0,else

c

c

 

...q

c f

, q

 

Q , c

 

si , i : si = rj

b = q 1 q

2

 

 

 

=

1

2

 

 

f

 

j

 

 

j

0,else

Например:

Пусть a = 180 , b = 350

a= 22 32 5 , b = 2 52 7 - канонические разложения.

a= 22 32 5 70 , b = 350 = 2 30 52 7 - разложения по числам из множества Q.

Теперь легко видеть, что

НОД(a,b) = q1min{r1 ,c1}q2min{r2 ,c2 }...qmin{f

rf ,c f }

(1)

НОК(a,b) = q1max{r1 ,c1}q2max{r2 ,c2 }...qmax{f

rf ,c f }

(2)

Под min{a,b} понимается минимальное из чисел a и b , а под max{a,b} -

максимальное из чисел a и b . Например, найдем НОД(1800,630):

1800 = 233252 630 = 2 32 5 7

72

НОД(1800,630) = 2 32 5 = 90

НОК(1800, 630) = 23 32 52 7 = 12600

Можно легко доказать (упражнение 16), что

a b = НОД(a,b) НОК(a,b)

(3)

Однако этот метод хорош скорее для теоретических построений, чем в качестве практического алгоритма. Задача разложения числа на простые множители – сложная задача, - гораздо сложнее, чем нахождение НОД (попробуйте разложить число 928734685 на простые множители). Хотелось бы вооружиться более простым способом решения нашей задачи. И такой способ есть. Называется он алгоритмом Евклида, и является одним из самых первых нетривиальных алгоритмов в истории науки.

Заключается он в следующем: пусть у нас есть 2 числа a и b . Найдем q1 =a mod b - остаток от деления числа a на число b .

Тогда число a представимо в виде

a = c1b + q1

(4)

Если q1 ≠ 0 , то делим число b на q1 , и получим новое выражение

 

b = c2 q1 + q2

(5)

Если q2 ≠ 0 , то делим число q1 на q2

q1 = c3q2 + q3

будем делить qi на qi+1 пока qi+1 ≠ 0

qn−1 = cn+1qn + qn+1

qn = cn+2 qn+1

Теперь докажем, что НОД(a,b) = qn+1

Подставляя выражение qn = cn+2 qn+1 в выражение для qn−1 , получим, что qn−1 Mqn+1 . Затем, подставляя выражения для qn−1 и qn в равенство для qn−2 , получим, что qn−2 Mqn+1 . И. т. д., поднимаясь по равенствам вверх, получим, что qi Mqn+1 ,i = 1, n , bMqn+1 , aMqn+1

То есть число qn+1 - общий делитель чисел a , b .

Докажем теперь, что qn+1 - наибольший из общих делителей чисел a и b . Предположим противное: пусть существует z – общий делитель чисел а и b: z > qk +1 . Из

(4) q1 = a c1b . Так как aMz bMz , то и q1 Mz . Аналогично из формулы (5) получим, что q2 Mz .

Продолжая эти рассуждения, в итоге получим qn+1 Mz . Но по предположению qn+1 < z . Получили противоречие. Значит qn+1 = НОД(a,b) .

Следующая программа реализует алгоритм Евклида с помощью цикла while.

Пример 5: Программа, которая находит НОД и НОК 2 введенных чисел.

1 : Uses Crt;

2 :

3 : var

4 : h,a,b,q:integer;

5 : begin

6 : Clrscr;

 

 

 

 

73

7

:

writeln('Введите, пожалуйста, 2 числа');

 

8

:

readln(a,b);

 

 

9

:

h:=a*b;

{Произведение чисел a и b надо

для вычисления НОК}

10:

q:=1;

{Если q=0, то цикл работать

не будет}

11:while q<>0 do

12:begin

13:q:=a mod b; {вычисляем остаток от деления чисел а и b}

14:a:=b;

15:b:=q;

16:end;

17:writeln('НОД чисел = ',a);

18:

h:=h div a;

{НОК(а,b) = a*b/НОД(a,b)}

19:writeln('НОК чисел = ',h);

20:readln;

21:end.

Вначале программы мы сохраняем произведение чисел a и b (строка 9). Переменной q присваиваем число 1 только с одной целью: чтобы цикл начал свою работу. Вместо 1 можно было бы присвоить любое другое число, 0 .

Вцикле while мы сначала вычисляем остаток от деления числа a число b. Но так как на следующем шаге цикла мы должны будем делить уже число b на число q, то надо сделать переприсваивание a:=b, b:=q. Затем переходим на новый виток цикла: проверяем условие q<>0. Если оно не выполняется, то начинается новый виток цикла: после вычисления остатка от деления a на b, на втором шаге цикла в переменной a будет записано число b, в переменной b число q1 , а в переменной q – число q2 . Затем

снова делаем переприсваивание, и. т. д., пока на каком-либо шаге цикла остаток от деления не станет равным 0. Как только q=0, то мы выходим из цикла, а НОД(a,b) будет находиться в переменной а.

Эту же самую программу можно написать и с помощью цикла repeat (тогда она будет занимать на несколько строк меньше, и выглядеть несколько элегантнее):

Пример 6: Реализация алгоритма Евклида с помощью цикла repeat.

1

: Uses Crt;

 

2

:

 

 

3

: var

 

4

:

h,a,b,q:longint;

5

: begin

 

6

:

Clrscr;

 

7

:

writeln('Введите, пожалуйста, 2 числа');

8

:

readln(a,b);

 

9

:

h:=a*b;

{Произведение чисел a и b надо для вычисления НОК}

10:repeat

11:q:=a mod b; {вычисляем остаток от деления чисел а и b}

12:a:=b;

13:b:=q;

14:until q=0;

15:writeln('НОД чисел = ',a);

16:

h:=h div a;

{НОК(а,b) = a*b/НОД(a,b)}

17:

writeln('НОК чисел = ',h);

 

74

18:readln;

19:end.

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

4.5. Процедуры break и continue

Процедура continue вызывает пропуск оставшейся части цикла, и начинается выполнение следующей итерации цикла.

Пример 7: Использование процедуры continue.

1

: var

 

2

:

n:integer;

 

3

:

spos,sneg:integer;

4

:

 

 

5

: begin

 

6

:

spos:=0; {Начальное количество положительных чисел равно 0}

7

:

sneg:=0; {Начальное количество отрицательных чисел равно 0}

8

:

repeat

 

9

:

read(n);

{вводим новое число}

10:if n>0 then {Если число положительно}

11:begin

12:inc(spos); {spos:=spos+1}

13:continue; {Переходит на новую итерацию цикла}

14:end;

15:if n<0 then {Если число отрицательно}

16:inc(sneg); {sneg:=sneg+1}

17:

until n=0;

{Если число=0 то цикл завершает свою работу}

18:writeln(' Количество положительных чисел = ',spos);

19:writeln(' Количество отрицательных чисел = ',sneg);

20:end.

Когда программа дойдет до слова repeat, начинается выполнение тела цикла (предварительных условий нет!): пользователь вводит число, и если оно положительно, то выполняется тело цикла (строка 10): кол-во положительных чисел увеличивается на 1, и затем с помощью процедуры continue программа переходит на начало цикла (второй условный оператор не выполняется).

С помощью процедуры break можно выходить из цикла. После выполнения процедуры break программа продолжит свою работу с первого оператора после оператора цикла, в котором находится процедура break. Но запомните: процедура break выходит только из одного оператора цикла!!!

Например, в следующем фрагменте программы после процедуры break будет выполняться процедура inc(d);

for i:=1 to 10 do begin

repeat writeln(i);

75

break;

s:=1;

read(h); until h=1; inc(d); end;

s:=sqr(h);

4.6. Проверка чисел на простоту

Простые числа интересны не только с точки зрения чистой математики. Разложение больших чисел (около 200 десятичных разрядов) на простые множители, если сами простые числа, участвующие в разложении, также велики, - очень трудная задача, и на данный момент не существует алгоритмов, позволяющих быстро выполнять разложение. Поэтому на основе этой проблемы строятся многие криптосистемы.

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

проверки на простоту числа n можно делить лишь на числа, n .

2

Следующая теорема дает более сильный результат.

Теорема: минимальный простой делитель составного числа n не превосходит n

 

Доказательство:

 

 

Пусть минимальный простой делитель числа n равен a . Предположим, что

теорема не верна, т.е. a > n . Так как n составное, то у него есть еще по крайней мере

один

делитель, не равный 1. Следовательно,

n a a > n n = n . получили

противоречие. Следовательно, a n .

 

 

Значит, чтобы проверить число n на простоту, мы может делить его на все числа

n .

Если мы нашли хоть одно число, на которое

число n разделится, то n

составное. Следующая программа реализует этот алгоритм.

Пример 8: Программа, печатающая простые числа в промежутке [2,n].

1

:

Uses Crt;

 

2

:

var

 

3

:

i,k,j,n:integer;

 

4

:

begin

 

5

:

Clrscr;

 

6

:

write('Введите число ');

7

:

readln(n);

 

8

:

write(2,' ');

 

9

:

for i:=3 to n do

{Просматриваем все числа}

10:

begin

{и проверяем их на простоту}

11:k:=round(sqrt(i)); {Наименьший простой делитель числа x

12:

 

лежит в промежутке [2,sqrt(x)]}

13:

for j:=2 to k do

{Делим i на числа 2..k}

76

14:begin

15:if (i mod j)=0 then {Если число i делится на j}

16:

break;

{то i - не

простое число}

17:

if j=k then

{Если i не

делится ни на одно из}

18:

write(i,' ');

{чисел 2..k, то i - простое}

19:end;

20:end;

21:readln;

22:end.

Первое простое число – 2. Мы его выводим отдельно от остальных (дело в том, что даже если мы начнем внешний цикл for с 2, а не с 3, то наша программа не выведет число 2 на экран (подумайте, почему)).

После того, как мы напечатали число 2, мы должны поочередно проверить на простоту все числа от 3 до n. Внутри внешнего цикла мы вычисляем i , а затем мы должны проверить, делится ли число i хотя бы на одно из чисел промежутка [2, i ]. Эту проверку мы выполняем в строке 15. Если мы нашли такое число j, что iM j , то мы должны выйти из цикла проверки числа на простоту, что и делает процедура break. Если же число i не разделилось ни на одно из чисел промежутка [2, i ] (проверка этого условия – в строке 17), то оно – простое, и мы должны его напечатать.

4.7. Как компьютер может вычислить значение функции?

Это вопрос не такой простой, каким он кажется на первый взгляд. На аппаратном уровне компьютер может лишь складывать и умножать целые и вещественные числа, а также вычислять остаток и неполное частное от деления двух целых чисел (т.е. операции mod, div). Никаких степенных функций, логарифмов и синусов компьютер сам по себе не вычисляет. Его надо научить это делать.

Какую функцию реализовать проще всего? – Естественно, возведение в натуральную степень. Чтобы вычислить xn достаточно n раз умножить число x само на себя. Можно возведение в степень реализовать намного лучше, но дело не в этом. Главное – что с помощью ЭВМ можно возводить число в натуральную и, следовательно, в целую степень.

С другими функциями дело обстоит сложнее. Однако есть универсальный способ, основанный на представлении функции в виде бесконечночлена (математики

называют его степенным рядом). Например: e x = 1+ x + x 2 + ... + x n + ... , причем это верно

1! 2! n!

для любых действительных чисел (иногда можно получить равенства, которые верны лишь на некотором интервале).

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

| bn+i

77

Приближенное вычисление бесконечных сумм

Для того, чтобы вычислить сумму членов произвольной конечной последовательности, достаточно просто просуммировать их. Гораздо сложнее дело обстоит с бесконечными суммами: в некоторых частных случаях, когда последовательность строится по определенному закону, можно вывести формулу, которая позволит точно вычислить сумму. Классическим примером является бесконечная убывающая геометрическая прогрессия, сумму элементов которой мы нашли в главе 1. Однако другие бесконечные суммы (математики говорят: суммы рядов) подсчитать не так просто, а в большинстве случаев и невозможно. Поэтому применяются приближенные формулы вычисления сумм рядов.

Итак, нам надо вычислить сумму S = b1 + b2 + ... + bn + ...

Как можно поступить: мы будем находить так называемые усеченные суммы Sn = b1 + b2 + ... + bn . Сначала найдем S1 , затем S2 , затем S3 и т.д. А прибавлять каждый

следующий член последовательности bn будем только если | bn |> ε , где ε - число,

которое задается в начале вычислений, и называется точностью вычислений. Фактически мы считаем, что если прибавление каждого следующего числа практически не изменит результата, то заданная точность вычислений достигнута, и вычисления можно прекращать.

Чтобы наш метод давал верные результаты, мы будем предполагать, что |<| bn | для любого натурального числа i , а также что сумма конечна и

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

Например, сумма 1+

1

+

1

+ ... +

1

+ ... - бесконечна, хотя ее слагаемые образуют

 

 

 

2

3

 

n

 

монотонно убывающую к нулю последовательность.

Теперь рассмотрим конкретный пример: найдем сумму 1+

x

+

x 2

+ ... +

x n

+ ... для

 

 

 

1! 2!

 

n!

 

любого наперед заданного числа х. Т.к. мы знаем, что этот бесконечночлен не что иное, как экспонента, то эта сумма конечна. Кроме того, как только выполнится | x |< n , то

каждое следующее слагаемое суммы будет по модулю меньше предыдущего, и убывание будет обратно факториалу, что очень быстро (быстрее, чем геометрическая прогрессия). Значит, приближенный метод вполне применим.

Напишем теперь код самой программы:

Пример 9: Приближенное вычисление суммы ряда.

1 : var

2 : i:integer;

3 : x,f,rat:real;

4 : eps:real;{Точность вычислений}

5 : begin

6 : writeln('Введите число x');

7 : readln(x);

8 : writeln('Введите точность вычислений');

9 : readln(eps);

10: {Присваиваем начальные значения вспомогательным переменным}

78

11:f:=1;

12:rat:=1;

13:i:=1;

14:repeat

15:rat:=rat*x/i;{Вычисляем значение следующего слагаемого}

16:inc(i);

17:

f:=f+rat;

{Прибавляем новый элемент ряда к сумме}

18:until abs(rat)<eps; {Если модуль слагаемого меньше eps,}

19:

{прекращаем вычисления}

20:writeln('Результат: ','exp(',x,') = ',f);

21:writeln('Результат процедуры, встроенной в ТР ',exp(x));

22:end.

Вданном примере число i – это номер слагаемого, которое вычисляется на данном витке цикла, rat – само i-е слагаемое, а f – сумма последовательности.

На первом шаге i=1, rat=1, f=1.

Так как,

x n+1

 

=

x x n

, то каждое следующее слагаемое можно получить из

 

 

 

 

 

(n +1)!

n +1 n!

 

 

 

предыдущего, умножая на х, и деля на номер слагаемого (строка 15). Поэтому мы можем обойтись без трудоемкой процедуры возведения числа в степень. В 16-й строке увеличиваем i, так как на следующем шаге мы будем вычислять следующий член последовательности. В 17-й строке мы прибавляем текущее слагаемое к сумме, и затем переходим на следующий виток цикла, если не выполняется условие в строке 18.

Сравните результаты наших с вами вычислений с результатом, который дает встроенная функция. Вы увидите, что мы все сделали правильно.

Итак: приближенное вычисление любой элементарной функции может быть сведено к операциям сложения, умножения и деления; следовательно, компьютер может вычислить их значение в любой точке за конечное время с

любой наперед заданной степенью точности.

В предыдущем утверждении очень важна фраза «с любой наперед заданной степенью точности». Дело в том, что если сумма a1 + a2 + ... + an + ... конечна, то для

любого ε > 0 существует k такое, что ak +1 + ak +2 + ... < ε . Однако каким будет это число k

- 10, 1000 или 1010 - в общем случае сказать нельзя. Если бы мы начали вычислять Sn = a1 + a2 + ... + an для всех n , то мы на каком-то шаге непременно получим значения

искомой суммы с любой степенью точности. Но можно подобрать такие суммы, что если мы зададим наперед точность ε , то мы не сможем узнать, когда нам надо приостанавливать вычисления - через минуту, день, год… Мы можем уже получить приближенное значение суммы, однако не сможем доказать, что оно таковым является. А если утверждается, что мы можем вычислить сумму с любой наперед заданной степенью точности, то это означает, что мы можем не только подсчитать приближенное значение суммы, но и доказать что оно таковым является и, следовательно, что мы можем прекращать дальнейшие вычисления.

Задачи

1.Написать программу вычисления факториала с помощью цикла repeat.

2.Вычислить сумму S = 12 + 22 + ... + n2 для наперед заданного числа n.

79

3.Логической переменной х присвоить значение true или false, в зависимости от того, является натуральное число k степенью 3 или нет.

4.Дано 8 вещественных чисел. Вычислить разность между минимальным и максимальным из них.

5.Дана непустая последовательность различных натуральных чисел, за которой следует 0. Определить порядковый номер наименьшего из них.

6.Дано число х. Придумать как можно более эффективный алгоритм и вычислить:

а) y = х10 + 9 + ... +10х +11; б) y = 11х10 +10х9 + ... + +1;

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

7.Вычислить y = 1!+ 2!+ 3!+ ... + n! ( n >0);

8.Числа Фибоначчи ( f n ) определяются формулами

f 0 = f1 =1; f n = f n−1 + f n−2 при n = 2, 3, …

a)определить 40-е число Фибоначчи;

b)найти первое число Фибоначчи, большее m ( m >1);

c)Вычислить s – сумму всех чисел Фибоначчи, которые не превосходят 1000.

9.Не используя стандартные функции (за исключением abs), вычислить с точностью eps>0:

 

x3

x5

x2n+1

y = shx = x +

 

+

 

+ ... +

 

+ ...

 

 

 

 

3!

 

5!

 

(2n +1)!

Считать, что необходимая точность достигнута, если очередное слагаемое по модулю меньше eps, - все последующие слагаемые можно уже не учитывать.

10.Дана непустая последовательность ненулевых целых чисел, за которой следует 0. Определить, сколько раз в этой последовательности меняется знак (например, в последовательности 1, -3, 4, 55, -4 знак меняется 3 раза).

11.Определить, является ли данное натуральное число совершенным, т.е. равным сумме всех своих положительных делителей, кроме самого себя (например, число 6

– совершенно, т.к. 1+2+3=6).

12.Составить программу печати таблицы температур по Цельсию от 0 до 100 градусов с шагом в один градус и их эквивалентов по шкале Фаренгейта, используя для

перевода формулу t F

=

9

tC + 32

 

 

5

 

13.В водоеме n тонн рыбы. Каждый год рыболовецкая бригада вылавливает x тонн. Воспроизводство рыбы – y % в год. Для сохранения воспроизводства нужно прекращать лов, когда в водоеме останется z тонн рыбы. Через сколько лет надо прекращать лов рыбы. Для простоты будем считать, что прирост популяции происходит мгновенно в конце года.

14.Дан прямоугольник размера a b . На первом шаге от него отсекают квадрат максимального размера, затем к оставшемуся прямоугольнику применяют аналогичную процедуру. И так до того момента, пока длина стороны отсекаемого квадрата не будет меньше c . Вычислить площадь прямоугольника, который остается от исходного после выполнения этой процедуры.

15.Дано натуральное число n . Найти сумму его цифр.

16.Докажите формулу ab = НОД(a,b) НОК(a,b)

80

17. НОД(x1 , x2 ,..., xn ) назовем наибольшее из чисел, на которые делятся все хi , i = 1, n .

Напишите программу, которая будет считать НОД n введенных натуральных чисел. 18. Проверьте, можно ли обобщить формулу из упражнения 16 следующим образом:

x1x2 ...xn = НОД(x1, x2 ,..., xn ) НОК(x1, x2 ,..., xn )

19.Напечатать все простые делители заданного натурального числа.

20.Дана последовательность положительных вещественных чисел х1 , х2 ,..., хn ( n заранее не известно), содержащая по крайней мере 1 число, за которыми следует отрицательное число. Вычислить величину

nx1 + (n − 1)x2 + ... + 2xn−1 + xn .

21. Если внимательно присмотреться к формулам

1+ 2 + ... + n =

n(n +1)

и

12 + 22 + ... + n2 =

n(n +1)(2n +1)

, то можно увидеть закономерность:

 

 

2

 

6

 

в правых частях обеих формул стоят многочлены от переменной n, со степенями на 1 выше, чем степени чисел, которые мы суммируем.

Обобщите результат, показав, что суммой 1p + 2p + ... + n p будем многочлен ( p +1)-й

степени.

22. Пользуясь результатом предыдущей задачи, найдите выражение для суммы

1p + 2p + ... + n p .

23.Вводится число n >0. Найти, сколькими нулями оканчивается n!. Число n! может быть таким большим, что не влезет в любой стандартный числовой тип ТP.

24.Пусть выражение из цифр получается последовательным выписыванием всех натуральных чисел: 1234567891011121314151617181920… По заданному числу k

выведите k -ю цифру последовательности.

25.Пусть последовательность из цифр получается так же, как и в задаче 24. Пусть

f (n) = m , если 10n -тая цифра выражения входит в состав т -значного числа. Например, f (2) = 2 , так как сотая цифра входит в состав двузначного числа 55. Найдите (с доказательством) f (1987) .

26.Обобщите формулы, полученные для сумм арифметической и геометрической прогрессии, подсчитав сумму первых n членов следующей последовательности:

an+1 = qan + d .

27.В первой части было доказано, что 2 - иррациональное число. Докажите:

Если число p - простое, а k > 1, k N , l < k , то k pl - иррациональное.

Используя основную теорему арифметики, исследуйте более общий случай: при каких значениях иррациональным будет число p n , n, p N .

28.Пусть вам даны канонические разложения целых чисел а , b . Исследуйте, при каком условии число loga b будет иррациональным.