Общие вопросы по математике
   
Как возвести (-1) в степень N?  
Является ли число степенью двойки?  
Двоичные числа, заданные строками: вычитание / перемножение  
Как вычислить арксинус / арккосинус аргумента?  
Разложение функции в ряд: Ln(x) / Exp(x)  
   


Как возвести (-1) в степень N?

Способ xa = Exp(a*Ln(x)) не подходит, т.к. для вычисления по этой формуле основание степени x должно быть положительным. Используем функцию:
function minusOnePower(n: integer): integer;
begin
	minusOnePower := (1 - 2*byte(Odd(n)));
end;


Является ли число степенью двойки?

function is_power_2(x: word): boolean;
begin
	is_power_2 := (x > 0) and ((x and Pred(x)) = 0)
end;


Вычитание двоичных чисел с использованием строк

function IntToBin(bin: longint): string;
var bin_s: string;
begin
	bin_s := '';
	if bin = 0 then bin_s := '0'
	else
		while bin <> 0 do begin
			if (bin and 1) = 1 then
				bin_s := '1' + bin_s
			else bin_s := '0' + bin_s;
			bin := bin shr 1;
		end;
	IntToBin := bin_s
end;

function BinToInt(bin_s: string): longint;
var
	bin, mult: longint;
	i: integer;
begin
	mult := 1; bin := 0;
	for i := length(bin_s) downto 1 do begin
		if bin_s[i] = '1' then bin := bin + mult;
		mult := mult shl 1;
	end;
	BinToInt := bin
end;

var
	BO, BT: string;

begin
	write('Введите первое число : ');
	readln(BO);
	write('Введите второе число : ');
	readln(BT);
	
	writeln( 'Результат: ', IntToBin(BinToInt(BO)-BinToInt(BT)) )
end.


Перемножение двоичных чисел с использованием строк

Внимание: для корректной работы программы вводить данные нужно следующим образом: более длинное число - первым, более короткое - вторым (одинаковые по длине числа могут вводиться в любом порядке)
{ Дополнительная функция, реализующая сложение двоичных чисел }
function add_binary(s1, s2: string): string;
var
	T, z: string;
	i: byte; shift: char;
begin
	{ Для удобства будем считать первой строкой более длинную строку... }
	if length(s1) < length(s2) then begin
		{ Если же длиннее вторая строка, то меняем ее местами с первой }
		T := s1; s1 := s2; s2 := T
	end;
	
	T := '';
	{ Дополняем короткую строку спереди нулями (если необходимо) }
	for i := 1 to length(s1) - length(s2) do s2 := '0' + s2;

	{ переменная содержит "сдвиг" }
	shift := '0';
	
	{
		проходим по всей строке (с конца в начало) и выполняем "побитное"
		сложение строк с учетом сдвига
	}
	for i := length(s1) downto 1 do begin
		{
			z содержит тройку значений:
			(1, 2) - очередные "биты" строк
			(3) - сдвиг
		}
		z := s1[i] + s2[i] + shift;
	
		{
			проверяем все возможные комбинации "троек" и добавляем 
			к результирующей строке спереди соответствующий "бит"
			(не забываем учитывать и изменять значение сдвига)
		}
		if z = '000' then T := '0' + T;
			
		if (z = '001') or (z = '010') or (z = '100') then begin
			T := '1' + T; shift := '0'
		end;
		
		if (z = '101') or (z = '011') or (z = '110') then begin
			T := '0' + T; shift := '1'
		end;
		
		if z = '111' then begin
			T := '1' + T; shift := '1'
		end;
	end;
		
	{ если есть необходимость, добавляем "сдвиговый" "бит" к строке }
	if (shift = '1') then T := '1' + T;
		
	{ и возвращаем результат - двоичную сумму строк s1 и s2  }
	add_binary := T
end;

const
	n = 4;
	{
		константы для проверки работоспособности... 
		s1: string = '0111';
		s2: string = '0010';
	}
	result: string = '0';
var
	i, j: byte;
	s1, s2, toadd: string;

begin
	write( 'Введите первое число: ' ); readln(s1);
	write( 'Введите второе число: ' ); readln(s2);

	for i := 1 to n do begin
		{ 1-я строка содержит в последнем бите 1 }
		if s2[ length(s2) ] = '1' then begin
			{
			для промежуточного результата нам необходимо значение 
			второй строки...
			}
			toadd := s1;

			{
			... сдвинутое на количество бит, соответствующее позиции 
			единицы в 1-ой строке
			}
			for j := 1 to pred(i) do toadd := toadd + '0';

			{ добавляем промежуточный результат к окончательному }
			result := add_binary(result, toadd)
		end;

		{ по окончании обработки очередного бита 1-ой строки удаляем его... }
		delete(s2, length(s2), 1)
	end;
		
	{ удаляем лидирующие (незначащие) нули из результата }
	while result[1] = '0' do
		delete(result, 1, 1);

	{ печатаем результат }
	writeln('result = ', result);
	readln;
end.


Как вычислить арксинус аргумента?

function ArcSin(x: real): real;
begin
	if (1 - Abs(x)) < 10E-3 then ArcSin := x * Pi/2
	else ArcSin := ArcTan( (x) / Sqrt(1 - Sqr(x)) )
end;


Как вычислить арккосинус аргумента?

function ArcCos(x: real): real;
begin
	if Abs(x) < 10E-3 then ArcCos := Pi/2
	else ArcCos := ArcTan(Sqrt(1 - Sqr(x)) / x) + Pi * Byte(x < 0)
end;


Как самому написать функцию Ln(x)?

Как самому написать функцию Ln(x), если бы ее не было в Паскале?

Разложением в ряд:

при X > 0

Ln(x) = 2 * ∑ [(x - 1)2n+1 / (2n+1)*(x+1)2n+1]

Теперь нужно просто написать функцию, подсчитывающую эту сумму:
function _Ln(x: double): double;
const eps = 0.0000001; { Задаем точность }
var
	s, next: double;
	n: integer;
begin
	next := (x - 1)/(x + 1);
	s := next; n := 1;
	repeat
		inc(n, 2);
		next := (next * sqr(x - 1))/sqr(x + 1);
		s := s + next/n;
	until (next/n) < eps;
	_Ln := 2 * s
end;


Как самому написать функцию Exp(x)?

Функция exp(x) раскладывается в такой ряд:

Exp(x) = 1 + x/1! + x2/2! + x3/3! + ... = ∑ xn / n!

Следовательно,
function _Exp(x: double): double;
const eps = 0.0000001; { Задаем точность }
var
	s, next: double;
	n: integer;
begin
	next := 1;
	s := next; n := 0;
	repeat
		inc(n);
		next := (next * x) / n;
		s := s + next;
	until (next < eps);
	_exp := s
end;




Free Web Hosting