Поддержка лекционной части курса Основы программирования
Был ли уже условный оператор? И если нет, то когда планируется?
По поводу бонусных трех баллов. Необходимо было написать универсальный алгоритм возведения х в степень n. Вот мой вариант.
var
x, n, i: integer;
xn: real;
begin
write ('Число: ');
readln (x);
write ('Степень: ');
readln (n);
xn := 1;
i := 0;
while i < abs(n) do
begin
xn := xn * x;
i := i + 1
end;
if n < 0 then
xn := 1 / xn;
writeln (xn:10:5);
end.
Алгоритм возведения числа в натуральную степень(ДЗ):
begin
var x := readreal;
var n := readinteger;
var res : real := 1;
while n > 0 do
begin
if (n and 1 = 0) then
begin
x *= x;
n := n shr 1;
end
else
begin
res *= x;
n -= 1;
end;
end;
print(res);
end.
function p (x,y:integer):integer;
var m: integer;
begin
m := 1;
while (y > 0) do
begin
if (y and 1 = 1) then
m := m * x;
x := x + x;
y := y shr 1;
end;
p := m;
end;
Не работает. Деление на 2 выполняется и для четных, и для нечетных Y. И сложение там не нужно.
“y and 1 = 1” - проверка на четность. я правильно тебя понял? если да, то почему именно таким образом?
да,увидела,спасибо
верно,планировалось именно как проверка на четность.По принципу “почему бы и нет”
var
x, y, st, r: real;
m: integer;
begin
readln(x, y);
if (x < 0) then
st := (-1) * Exp(y * Ln(Abs(x)))
else
if (x > 0) then
st := Exp(y * Ln(Abs(x)))
else
st := 0;
m := round(y);
if (m mod 2 = 0) then
R := Abs(st);
if (y = 0) then
st := 1;
writeln(st);
end.
как вариант через экспоненту/логарифм
Это же: power(x,n); Вычисление логарифма и экспоненты требует намного больше ресурсов, чем умножение.
Возведение числа в натуральную степень
begin
var x := readreal;
var n := readinteger;
var power : real := 1;
while n > 0 do
begin
if (n and 1 = 1) then
power *= x;
x *= x;
n := n div 2;
end;
println(power);
end.
//Возможно есть лучший алгоритм, но хоть работает и уменьшает кол-во умножений
var
x,n,k:integer;
s,m:real;
a,b,dis:integer;
t1,t2,t3:BigInteger;
Begin
write('Основание:');
readln(x);
write('Степень(>=4):');
readln(n);
t1:=1;
t2:=1;
t3:=1;
s:=Trunc((ln(Trunc(n/2))/ln(2)));
m:=Trunc(n/(2*s));
dis:=Trunc(n-2*m*s);
a:=dis div Trunc(s);
b:=dis mod Trunc(s);
for var i:=1 to Trunc(s) do
t1*=x;
for var i:=1 to Trunc(m) do
t2*=t1;
t3:=t2*t2;
for var i:=1 to a do
t3*=t1;
for var i:=1 to b do
t3*=x;
k:=Trunc(s)-1+Trunc(m)-1+1+a+b;
writelnFormat('{0}^{1}={2}',x,n,t3);
writeln('Количество умножений:',k);
end.
{
Лог:
Основание:2
Степень:6
2^6=64
Количество умножений:3
Основание:3
Степень:897
3^897=95009161123575509487351704781088869938617224968466170303382900843729981391283919691164882664197959088504417084098297169055790972369938213220938911078242284999919071499869139981768195924855915761275737321875981297858361822710733623890018339420314312678414112106464281875678934335899626687582223979042456389921303116179345175869062457591662665121821558114220781174709278473033080178547607090094610212237198288445045715853644136963
Количество умножений:64
}
Вот мой вариант программы ( правда,не уверенна,что она будет быстро работать,да и памяти уходит много):
function Power(x, n: integer): integer;
begin
if n = 0 then result := 1
else if n = 1 then result := x
else
if n = 2 then result := x * x
else
if (n mod 2) = 0 then
result := Power(x, n div 2) * Power(x, n div 2)
else
result := Power(x, (n - 1) div 2) * Power(x, (n - 1) div 2) * x;
end;
begin
var x := ReadInteger('Введите х:');
var n := ReadInteger('Введите степень :');
writeln('Получившееся число:', Power(x, n));
end.
Уважаемые студенты!
Пожалуйста, используйте средства оформления кода на форуме:
```
begin
мой код
end.
```
Работает на всех случаях, получился громоздкий, но толко на вид. Количество переменных минимально, и сам упакован в функцию для удобства. Надеюсь он лучше, чем просто power().
function Xpower(x,n:integer):integer; //Автор: Тактаров Евгений 1.9 дата: 15.09.15
var t:integer;
begin
If n mod 2=0 then
begin
t:=x*x;
n:=n div 2;
while n>1 do
begin
t:=t*t;
n:=n div 2;
end;
end
else
begin
t:=x;
while n>1 do
begin
t:=t*t;
n:=n div 2;
end;
t:=t*x;
end;
result:=t;
if n=0 then result:=1;
end;
begin
writeln(Xpower(2,9)); // тестовое исполнеие функции - можно вставить значения для проверки
end.
If сегодня уже был.
О, вот хорошо, спасибо.
2Sirenity Это конечно очень простой вариант, требующий n-1 умножения.
2Eselkopf Это уже лучше - этот алгоритм основан на степени двойки. Не оптимален, но хорош и прост
2Anastasiya_Belova Первый алгоритм я не понял, там внезапно возникает сложение x := x + x; - сложение нельзя использовать Второй алгоритм использует exp и ln, что конечно для чисел правильно, но задача стояла - использовать только умножения. Если x - многочлен или матрица, логарифм Вы не возьмёте. y := y shr 1; - проще y := y div 2. И аналогично чётность. Трудно читать
2Ilya_Yakubovskij Опять-таки, этот алгоритм основан на делении степени на 2 - это просто и хорошо, но неоптимально. x^15 как раз - пример, на котором это рушится
2Nan - хорошая попытка, но ничего не объясняется, поэтому трудно разобрать. Для x^15 сколько умножений требуется?
2Haku Хороший код, та же идея - делить на 2 степень если n четно, но Вы повторно вычисляете например Power(x, n div 2), поэтому у Вас в итоге n умножений - надо использовать функцию sqr или промежуточную переменную
2je_day Код немного закрученный, но, видимо, работает неверно - по ветке n- четно Вы далее предполагаете, что и после деления на 2 n останется четным
В любом случае - спасибо всем, кто принял участие в решении! Оперативно! Молодцы!
var shag: integer;
function pow(x: real; n: integer): real;
begin
var res: real;
res := 1;
if ((n and 7) = 7) and (((n mod 3) = 0) or ((n mod 3) = 1)) then
begin
var t: array [0..100] of real;
var i := 6;
t[1] := x;
var j := 3;
t[j] := x * x * x;
shag := 2;
while i <= n do
begin
i *= 2;
j *= 2;
t[j] := t[j div 2] * t[j div 2];
shag += 1;
end;
res := t[j];
i := i div 2;
while (i < n) and (j > 1) do
begin
j := j div 2;
if (i + j) <= n then
begin
res *= t[j];
shag += 1;
i += j;
end;
end;
end
else
begin
var t: array [0..100] of real;
var i := 4;
t[1] := x;
var j := 2;
t[j] := x * x;
shag := 1;
while i <= n do
begin
i *= 2;
j *= 2;
t[j] := t[j div 2] * t[j div 2];
shag += 1;
end;
res *= t[j];
i := i div 2;
while (i < n) and (j > 1) do
begin
j := j div 2;
if (i + j) <= n then
begin
res *= t[j];
shag += 1;
i += j;
end;
end;
end;
result := res;
end;
begin
var x := ReadReal('Введите число: ');
var n := ReadInteger('Введите степень: ');
var res1 := pow(x, n);
writeln(res1);
writeln(shag);
end.