Экспонента Кобола с очень высокими числами: нахождение 5 ** 365 и т. Д.
** используется для вычисления значений степени в Коболе. Это работает нормально с "маленькими" числами, например, 5 ** 10 и так далее.
Теперь есть задача, где мы должны найти X ** 365 + X ** 364 + X ** 363 + X ** 362 + X ** 361 + ... и т. Д., Где X - десятичное число с V9(02),
Если ** используется с более высокими числами, например, 5,00 ** 41, то происходит усечение позиций старших разрядов из-за того, что я могу сохранить PIC S9(29)V9(02) COMP-3 MAX (31 цифра) с опцией CBL ARITH(EXTEND).
Есть ли обходной путь для этой / экспоненциальной функции?
Возможно ли это вообще на Cobol Enterprise для z/Os?
2 ответа
Некоторые проблемы:
Первый, 5 ** 365
требуется 255 цифр.
Вторая картинка S9(29)V9(02)
требует, чтобы x
быть несколько меньше чем 1.2
,
Тем не мение, x
определяется как V9(02)
(если не было чего-то большего). Обходной путь - это логарифмы. ФУНКЦИЯ LOG10 доступна в Enterprise COBOL.
identification division.
program-id. big-exp.
data division.
1 x binary pic v99 value 0.99.
1 log10-of-x comp-2.
1 value-of-x-to-n comp-2.
1 sum-of-values comp-2 value 0.
1 disp-sum pic z(3).9(15).
1 n binary pic 9(3).
procedure division.
begin.
compute log10-of-x = function log10 (x)
perform varying n from 365 by -1
until n = 0
compute value-of-x-to-n = 10 ** (log10-of-x * n)
compute sum-of-values = sum-of-values +
value-of-x-to-n
end-perform
move sum-of-values to disp-sum
display disp-sum
stop run
.
За x = 0.99
ответ примерно 96.473721519223000
,
Но обратите внимание, что, как х падает ниже примерно 0.10
может произойти недостаточное заполнение.
Вы можете попробовать что-то вроде этого
Массив big-one похож на числовое поле длиной 1000 байт. т.е. рис 9(1000)
Для "5 ** 365", вы установите Mult на 5, а тимьян на 365.
Так как обычный кобол не будет поддерживать арифметику для таких больших чисел, вы должны сделать это самостоятельно.
Начните с установки big9(1000) в 1. Это похоже на значение pic 9(1000) 1.
Затем выполните цикл "тимьян", умноженный на абзац "do-mult", который умножает цифры big-one на "mult", обрабатывая любой "karry", добавляя его к промежуточному результату при вычислении предыдущей цифры.
В конце цифры big-one представляют результат.
IDENTIFICATION DIVISION.
PROGRAM-ID. cb043.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
DATA DIVISION.
FILE SECTION.
WORKING-STORAGE SECTION.
01 sub1 pic 9(05).
01 big-one.
03 big9 occurs 1000 pic 9(01).
01 mult pic 9(06) value 5.
01 thymes pic 9(03) value 365.
01 sub2 pic 9(05).
01 sub3 pic 9(05).
01 interm pic 9(10).
01 filler redefines interm.
03 karry pic 9(09).
03 rite pic 9.
01 staw pic 9(09).
PROCEDURE DIVISION.
MAINLINE.
******* обнулять большой массив
perform varying sub1
from 1 by 1
until sub1 > 1000
move 0 to big9(sub1)
end-perform.
******* сделать большой 1 как рис 9(1000) значение 1
MOVE 1 to big9(1000).
******* сделать умножение "тимьян" раз
perform varying sub2
from 1 by 1
until sub2 > thymes
perform do-mult
end-perform.
******* найти первую ненулевую цифру
perform varying sub1
from 1 by 1
until big9(sub1) not = 0
end-perform.
******* отобразить цифры результата
perform varying sub2
from sub1 by 1
until sub2 > 1000
display sub2 big9(sub2)
end-perform.
stop run.
do-mult.
******* обнулять сохраненное поле переноса "staw"
move 0 to staw.
******* умножьте каждую цифру "большой один"
******* начиная с big9(1000) и возвращаясь к big9 (1)
******* в левой руке 9 байт "interm", обозначают любой перенос, как "карри"
*******, который хранится в "staw" и добавляется, когда следующий расчет
******* сделанный
perform varying sub3
from 1000 by -1
until sub3 = 0
compute interm = (big9(sub3) * mult)
+ staw
move karry to staw
move rite to big9(sub3)
end-perform.