Читая
в Википедии статью про логарифм наткнулся на абзац рассказы
вающий о логарифмических предста
влениях чисел. Решил (используя ИИ) посмотреть как они эффекти
вны на обычном ПК (там го
ворилось, что им нужно специальное "железо", для проя
вления их эффекти
вности). Результат получился не очень (
в 3 раза медленнее чем обычно
вместо ускорения), но может быть
всё ра
вно какой-то интерес (скорее для расширения кругозора) это может предста
влять. Тем более
в принципе такое "железо"
выпускалось реально. Если интересно могу кроме этой начальной
версии показать
весь диалог с ИИ. А может и можно что-то
в нём ускорить и он станет быстрее.
- Код: Выделить всё
unit logoptunit;
{
Logarithmic number system (LNS) unit.
Version: 1.
Written on FreePascal (https://freepascal.org/).
Copyright (C) 2025 Artyomov Alexander
http://self-made-free.ru/
aralni@mail.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
}
{$mode objfpc}{$H+}
interface
type
TLogNumber = record
LogAbs: Double; // логарифм модуля
Sign: ShortInt; // -1, 0, 1
end;
function MakeLogNumber(X: Double): TLogNumber;
function LogToFloat(L: TLogNumber): Double;
function LogMul(A, B: TLogNumber): TLogNumber;
function LogDiv(A, B: TLogNumber): TLogNumber;
function LogPow(A: TLogNumber; Exponent: Double): TLogNumber;
function LogSqrt(A: TLogNumber): TLogNumber;
implementation
uses Math, SysUtils;
procedure FatalError(const Msg: String);
begin
Writeln(StdErr, 'LogOptUnit error: ', Msg);
Halt(200);
end;
function MakeLogNumber(X: Double): TLogNumber;
begin
if X = 0.0 then
begin
Result.LogAbs := 0.0;
Result.Sign := 0;
end
else
begin
Result.LogAbs := Ln(Abs(X));
Result.Sign := Sign(X);
end;
end;
function LogToFloat(L: TLogNumber): Double;
begin
if L.Sign = 0 then
Result := 0.0
else
Result := L.Sign * Exp(L.LogAbs);
end;
function LogMul(A, B: TLogNumber): TLogNumber;
begin
if (A.Sign = 0) or (B.Sign = 0) then
Exit(MakeLogNumber(0.0));
Result.LogAbs := A.LogAbs + B.LogAbs;
Result.Sign := A.Sign * B.Sign;
end;
function LogDiv(A, B: TLogNumber): TLogNumber;
begin
if B.Sign = 0 then
FatalError('Division by zero in LogDiv');
if A.Sign = 0 then
Exit(MakeLogNumber(0.0));
Result.LogAbs := A.LogAbs - B.LogAbs;
Result.Sign := A.Sign * B.Sign;
end;
function LogPow(A: TLogNumber; Exponent: Double): TLogNumber;
begin
if A.Sign = 0 then
Exit(MakeLogNumber(0.0));
Result.LogAbs := A.LogAbs * Exponent;
if Frac(Exponent) = 0 then
begin
// целая степень
if Odd(Trunc(Exponent)) then
Result.Sign := A.Sign
else
Result.Sign := 1;
end
else
begin
if A.Sign < 0 then
FatalError('Negative number to fractional power in LogPow');
Result.Sign := 1;
end;
end;
function LogSqrt(A: TLogNumber): TLogNumber;
begin
Result := LogPow(A, 0.5);
end;
end.
- Код: Выделить всё
program testlogopt;
{
Logarithmic number system (LNS) unit test.
Version: 1.
Written on FreePascal (https://freepascal.org/).
Copyright (C) 2025 Artyomov Alexander
http://self-made-free.ru/
aralni@mail.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
}
uses
logoptunit;
var
a, b, c: TLogNumber;
begin
a := MakeLogNumber(2.0);
b := MakeLogNumber(8.0);
c := LogMul(a, b);
Writeln('2 * 8 = ', LogToFloat(c):0:2);
c := LogDiv(b, a);
Writeln('8 / 2 = ', LogToFloat(c):0:2);
c := LogPow(a, 3);
Writeln('2 ^ 3 = ', LogToFloat(c):0:2);
c := LogSqrt(b);
Writeln('sqrt(8) = ', LogToFloat(c):0:4);
end.
- Код: Выделить всё
program test_logopt_speed;
{$MODE OBJFPC}{$H+}
{
Logarithmic number system (LNS) unit. Speed test.
Version: 1.
Written on FreePascal (https://freepascal.org/).
Copyright (C) 2025 Artyomov Alexander
http://self-made-free.ru/
aralni@mail.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
}
uses
logoptunit, sysutils, math, DateUtils;
const
N = 1000000;
var
i: Integer;
normalA, normalB, normalResult: array of Double;
logA, logB, logResult: array of TLogNumber;
tStart, tEnd: TDateTime;
totalNormal, totalLog: Double;
begin
Randomize;
SetLength(normalA, N);
SetLength(normalB, N);
SetLength(normalResult, N);
SetLength(logA, N);
SetLength(logB, N);
SetLength(logResult, N);
// Инициализация массивов
for i := 0 to N - 1 do
begin
normalA[i] := Random * 1000 + 1e-3; // не ноль
normalB[i] := Random * 1000 + 1e-3;
logA[i] := MakeLogNumber(normalA[i]);
logB[i] := MakeLogNumber(normalB[i]);
end;
// Обычное умножение
tStart := Now;
for i := 0 to N - 1 do
normalResult[i] := normalA[i] * normalB[i];
tEnd := Now;
totalNormal := 0;
for i := 0 to N - 1 do
totalNormal += normalResult[i];
Writeln('Обычное умножение: ', MilliSecondsBetween(tEnd, tStart), ' мс');
// Логарифмическое умножение
tStart := Now;
for i := 0 to N - 1 do
logResult[i] := LogMul(logA[i], logB[i]);
tEnd := Now;
totalLog := 0;
for i := 0 to N - 1 do
totalLog += LogToFloat(logResult[i]);
Writeln('Логарифмическое умножение: ', MilliSecondsBetween(tEnd, tStart), ' мс');
// Простая проверка (сумма результатов)
Writeln('Сумма обычных результатов: ', totalNormal:0:4);
Writeln('Сумма логарифмических результатов: ', totalLog:0:4);
end.
- Код: Выделить всё
./test_logopt_speed
Обычное умножение: 10 мс
Логарифмическое умножение: 29 мс
Сумма обычных результатов: 250092748142.3317
Сумма логарифмических результатов: 250092748142.3317