Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Программа находит решение уравнения ln((x - 1) / 3) / 3 = 0
- * методом Ньютона с подвижным полюсом
- */
- /******** MAIN.CPP ********/
- #include <iostream> // cin, cout
- #include <iomanip> // setprecision
- using std::cout;
- using std::endl;
- /**
- * Процедура реализует метод 'Ньютона с подвижным полюсом'
- * Возвращает значение X в уравнении ln((x - 1) / 3) / 3 = 0
- * С точностью |X - nextX| < accuracy
- */
- extern "C" void __fastcall calculate();
- extern "C" float X = 1.5f; // Начальное значение
- extern "C" float NextX = NULL; // Следующее значение функции
- extern "C" float accurecy = 1e-6f; // Точность |X - NextX|
- int main() {
- cout << X << endl;
- calculate();
- cout << std::setprecision(10) << NextX << endl;
- return 0;
- }
- /******** FUNCT.ASM ********/
- .386
- .MODEL FLAT;
- EXTERN _X: DWORD
- EXTERN _NextX: DWORD
- EXTERN _accurecy: DWORD
- .DATA
- BUFFER DWORD 0.0
- THREE DWORD 3.0 ; Константа 3
- TWO DWORD 2.0 ; Константа 2
- .CODE
- ; Получаем значение функции f(x) = ln((x - 1) / 3) / 3
- ; Постфиксная запись f(x) = x 1 - 3 / ln 3 /
- ; Входное значение _X
- ; Выходное значение BUFFER
- getF PROC
- fld1 ; Для логарифма...
- FLD _X ; Загружаем X
- FLD1 ; Загружаем 1
- FSUB ; Отнимаем от X, 1
- FLD THREE ; Загружаем в стек 3
- FDIV ; Делим первый раз на три
- ; Натуральный логарифм X = ln(X) = ln(2) * log2(X) = fyl2x(fldln2, X)
- ; URL: http://www.cyberforum.ru/assembler/thread525843.html
- FYL2X ; st(0) = st(1) * log2( st(0) )
- FLDLN2 ; st(0) = ln(2) st(1) = (X - 1) / 3
- FMUL
- FLD THREE ; Загружаем в стек 3
- FDIV ; Делим второй раз на три
- FSTP BUFFER ; Сохраняем значение в переменную BUF
- RET
- getF ENDP
- ; Получаем значение производной функции fdx(x) = 1 / (3 * (x - 1))
- ; Постфиксная запись fdx(x) = 1 3 x 1 - * /
- ; Входное значение _X
- ; Выходное значение BUFFER
- getFdx PROC
- FLD1
- FLD THREE
- FLD _X
- FLD1
- FSUB
- FMUL
- FDIV
- FSTP BUFFER
- RET
- getFdx ENDP
- ; Получаем значение xk+1 = xk + f(xk) * (f(xk) - 2) / 2 * fdx(xk)
- ; Постфиксная запись xk+1 = xk f(xk) f(xk) 2 - * 2 / fdx(xk) * +
- ; Входное значение (xk) _X
- ; Выходное значение (xk+1) _NextX
- next PROC
- FLD _X ; Загружаем X
- call getF ; Вычисляем f(xk)
- FLD BUFFER ; Загружаем f(xk)
- FLD BUFFER
- FLD TWO
- FSUB
- FMUL
- FLD TWO
- FDIV
- call getFdx ; Вычисляем fdx(xk)
- FLD BUFFER ; Загружаем fdx(xk)
- FMUL
- FADD
- FSTP _NextX
- RET
- next ENDP
- @calculate@0 PROC
- ; Инициализируем сопроцессор
- FINIT
- call next;
- @start:
- FLD _X ;
- FLD _NextX ; Сравниваем точность нашего решения, которая вычисляется
- FSUB ; по формуле |_X - _NextX|
- FABS ; с заданной точностью, которая хранится в accurecy
- ;
- FLD _accurecy ;
- FCOMIP ST(0), ST(1) ;
- ; Если наше реiение точно, то переходим на метку @exit
- JNC @exit ; Иначе продолжаем цикл
- MOV EAX, _NextX
- call next ; Получаем xk+1
- MOV _X, EAX
- call next ; Какого хуя это тут нужно?!
- loop @start
- @exit:
- RET
- @calculate@0 ENDP
- END
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement