Письменный вывод расширенного типа данных как с плавающей точкой, а не как научное выражение - PullRequest
0 голосов
/ 18 ноября 2018

Спокойной ночи, у меня проблема с writeln на Embarcadero 10.2, я пытаюсь написать функцию sin () как бесконечную серию расширений Тейлора.

Все работает нормально, но вывод находится в научном выражении, например: 3.60448486921676E-0158, когда правильным было 0.912945250727627654376099983845.

Мне нужна точность 30 цифр.Мой код ниже, это консольная программа.

program Project1;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  Windows,
  Math;

function fact(n: LongInt): extended;
begin
  if (n = 0) then
     fact := 1
  else
     fact := n * fact(n - 1);
end;

var
  one:integer;
  fin:extended;
  number:LongInt;
  i:integer;
  cons:LongInt;
  cons1:extended;
begin
  one := -1;
  writeln('Digite o angulo em radianos para o Seno: ');
  readln(number);
  for i := 1 to 120 do
  begin
    cons := (2*i)+1;
    if(i mod 2) = 0 then 
      one := 1
    else 
      one := -1;
    cons1 := fact(cons);
    fin := (one/cons1)*(power(number,cons));
    cons := 0;
  end;
  writeln(fin);
  readln;

end.

Ответы [ 3 ]

0 голосов
/ 18 ноября 2018

Вычисление sin(x) с расширением Тейлора стабильно только для небольших аргументов, скажем, меньше, чем Pi / 2.Для более крупных аргументов вы страдаете от катастрофической отмены, потому что промежуточные термины очень велики, например, для x=100 самые большие термины - это 49-й со значением 0.107151028812546692318354675952E43.Все эти большие термины складываются вместе и дают значение sin () с величиной <= 1.Вам понадобится около 70 десятичных цифр, вычислите результат примерно с 30 цифрами.

Решения таковы: Используйте процедуры сокращения диапазона и многоточные операции с плавающей точкой (см. mpf_sin в моем Pascal с открытым исходным кодом MPArith пакет).С помощью интерактивного калькулятора вы получите

sin(100) = -0.5063656411097587936565576104597854321 за 0,2 мс.

0 голосов
/ 19 ноября 2018
program Project1;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;


function sine(n: real): real;
asm
fld n
fsin
fstp Result
end;

var
n:real;
begin
write('Write the number: ');
readln(n);
writeln(sine(n):10:11);
readln;
end.
0 голосов
/ 18 ноября 2018

Чтобы выполнить вычисления с очень большой точностью, вам нужна библиотека для арифметики произвольной точности - используйте обертку / интерфейс Delphi для GMP или библиотеку Delphi. Пример . Еще один .

Обратите внимание, что для библиотек с поддержкой только длинных целых чисел (не с плавающей точкой) вы все равно можете вычислять ряды, как этот код Python (он имеет внутреннюю поддержку больших целых чисел. **power, // is div).
Единственное деление (медленная операция) выполняется один раз.

d30 = 10**30
d60 = d30 * d30
x = 3141592653589793238462643383279 // 4   #Pi/4 * d30
xx = - x * x
denom = d30
nom = x
sum = nom
i = 2
while abs(nom) * d30 > denom:
    nom =  nom * xx
    mul = i * (i + 1) * d60
    denom = denom * mul
    sum = sum * mul + nom
    i += 2

print('0.' + str(d30 * sum // denom))

>> 0.707106780551955811469384356540

Подход основан на этом: x - x^3/6 + x^5/120 = (x*120 - x^3 * 20 + x^5) / 120

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