|
Программирование >> Немодифицирующие последовательные алгоритмы
Пользователь программы должен задать п - требуемое количество десятичных знаков после запятой. Например, в выводе программы число % будет представлено как 1415 если п равно 4. Так как мы приближенно представляем вещественные числа с помощью целых, то должны обращать внимание на последние цифры результата, чтобы избежать ошибок округления, связанных с нашим приближенным вычислением функции arctan. Поэтому будем использовать коэффициент масштабирования TenPower-\0 * (3) и опустим последние три цифры при выводе результата. Вместо % мы на самом деле будем вычислять целое число, приблизительно равное TenPower х к. В соответствии с формулой (1) переменная х в уравнении (2) может принимать значения, равные 1Д, где k = 18, 57 или 239. Умножая уравнение (2) на большую константу N, мы получим следующее приближение, где вторая строка содержит только целые числа: Л arctan х = N arctan (1 /к) ~ N/k - N/{W) + N/{51) - N/(7k) + ... = Atan(k, N) (4) Здесь Л является большим целым числом, а оператор деления / означает целочисленное деление (как в выражении 39/5 = 7). В результате многоточие в выражении (4) обозначает конечное количество членов N/(W), поэтому мы можем вычислить все эти значения. После этого из формулы (1) следует, что TenPower х к приблизительно равняется следующему большому числу: Atan(i8, 48 х TenPower) + Atanlsi, 32 X TenPower) -Atanl239, 20 x TenPower) Следующая программа использует это выражение в вычислениях: largepi.cpp: Используем целые числа класса large для вычисления числа Пи. Скомпоновать с large.срр. ttinclude <fstream> ttinclude <time.h> ttinclude <stdlib.h> ttinclude large.h Для вычисления Пи: large Atan(uint к, const large &N) { Вычисляет N * atan(1.0/k) как целое число класса large large а = О, W = N * к, zero = О, к2 = к * к, i = -1, two = 2; cout к = к endl; while (w != zero) { a += (w /= k2)/(i += two); a -= (w /= k2)/(i += two); return a; void PiOutput(ostream &os, ofstream &ofile, const large &x, int n) { vector<char> s; x.num2char(s); Символьное представление x находится в s в обратном порядке. vector<char>::reverse iterator i; int к = 0; char ch; for {i=s.rbeginO ; i != s.rendO; ++i) { ch = *i; OS ch; if (ofile) ofile ch; После десятичной точки напечатано к цифр. if (к == 0) { OS . endl; if (ofile) ofile . endl; } else if (k % 50 == 0) { OS endl; if (ofile) ofile endl; } else if (k % 10 == 0) { OS ; if (ofile) ofile ; if (k++ == n) break; int main() { int n, m; cout Computation of pi. Number of decimals: ; cin >> n; m = n + 3; cout Copy of output to file pi.txt desired (y/n)? ; char answer; cin >> answer; ofstream ofile; if (answer == Y II answer == y) ofile.open( pi.txt ); large TenPower, Pi; clock t tStart, tEnd; tStart = clock 0; TenPower = power(5, m) ; TenPower = m; Быстрее, чем TenPower = power(10, m); Pi = (Atan(18, TenPower * 48) + Atan(57, TenPower * 32) - Atan(239, TenPower * 20))/1000; tEnd = clock(); cout Digits of pi: endl; PiOutput(cout, ofile. Pi, n); cout \nTime: (tEnd - tStart) ticks\n ; return 0; Для n, существенно больших 1000, выполнение программы начинает занимать ощутимое время. Чтобы предоставить пользователю информацию о текущем состоянии расчетов, желательно показывать промежуточный вывод для каждого из следующих шагов: 1. Вычисление TenPower = Ю , где т = п + Ъ. 2. Вычисление Atan(239, TenPower * 20). 3. Вычисление Atan(57, TenPower * 32). 4. ВычислениеЛга/г( 18, TenPower* 48). 5. Перевод переменной Pi класса large в символьную строку, содержащую п десятичных цифр для вывода. На шаге 1 мы оптимизируем наши расчеты с помощью операции сдвига влево, заметив, что Ю = Зх 2 . Отсюда мы можем вычислить значение б , а затем сдвинуть результат на т двоичных позиций влево. Поскольку время вычисления произведения чисел класса large зависит от их длины, мы можем вычислить значение 5 быстрее, чем Ю .
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |