Файл: А. Б. Шнейвайс основы программирования.pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 06.12.2023

Просмотров: 313

Скачиваний: 6

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

14.10
Примеры работы с функцией dprod program ts_prod1; implicit none real(4)
a,
b real(8)
a0, b0, a8, b8, aa, bb, cc, dd, ee, ff, gg a=5.2;
write(*,*) ’
a=’, a a0=a;
write(*,*) ’
a0=’, a0
a8=real(a,kind=8); write(*,*) ’
a8=’, a8
b=2.3;
write(*,*) ’
b=’, b b0=b;
write(*,*) ’
b0=’, b0
b8=real(b,kind=8); write(*,*) ’
b8=’, b8
aa=5.2d0;
write(*,*) ’
aa=’, aa bb=2.3d0;
write(*,*) ’
bb=’, bb cc=aa*bb;
write(*,*) ’
cc=aa * bb=’, cc dd=5.2*2.3;
write(*,*) ’
dd=5.2 * 2.3
=’, dd ee=a*b;
write(*,*) ’
ee= a * b
=’, ee ff=dprod(5.2,2.3); write(*,*) ’ ff=dprod(5.2,2.3)=’, ff gg=dprod( a , b ); write(*,*) ’ gg=dprod( a , b )=’, gg a=0.5;
write(*,*) ’
a=’, a b=3.5;
write(*,*) ’
b=’, b ee=a*b;
write(*,*) ’
ee= a * b
=’, ee gg=dprod( a, b);
write(*,*) ’ gg=dprod( a , b )=’, gg a=3.72382;
b=2.39265
aa=3.72382_8;
bb=2.39265_8; write(*,*) a*b, dprod(a,b), aa*bb end a=
5.1999998
a0=
5.1999998092651367
a8=
5.1999998092651367
b=
2.3000000
b0=
2.2999999523162842
b8=
2.2999999523162842
aa=
5.2000000000000002
bb=
2.2999999999999998
cc=aa * bb=
11.959999999999999
dd=5.2 * 2.3
=
11.959999084472656
ee= a * b
=
11.959999313354501
ff=dprod(5.2,2.3)=
11.959999313354501
gg=dprod( a , b )=
11.959999313354501
a=
0.50000000
b=
3.5000000
ee= a * b
=
1.7500000000000000
gg=dprod( a , b )=
1.7500000000000000 8.9097977 8.9097974404429010 8.9097979230000011
Возможен вопрос: Когда может быть выгодно получить произведение двух чисел типа real(4) в форме real(8) при сохранении погрешности округления типа real(4)?
399

14.11
Примеры работы с функциями max и min program ts_minmax implicit none integer a, b, c, aa(3), bb(4), cc(5)
a=4; b=6; c=-3; write(*,*) ’ max(a,b,c)=’,max(a,b,c)
write(*,*) ’ min(a,b,c)=’,min(a,b,c)
aa=(/1,2,3/);
bb=(/-9,3,7,-10/)
cc=(/0,1,2,3,4/)
write(*,*) ’ aa: ’, aa; write(*,*) ’ bb: ’, bb write(*,*) ’ cc: ’, cc write(*,*) ’maxval(aa)=’,maxval(aa)
write(*,*) ’Наибольший из максимальных:’
write(*,*) ’max(maxval(aa),maxval(bb),maxval(cc))=’,
>
max(maxval(aa),maxval(bb),maxval(cc))
write(*,*) ’minval(aa)=’,minval(aa)
write(*,*) ’Наименьший из минимальных:’
write(*,*) ’min(minval(aa),minval(bb),minval(cc))=’,
>
min(minval(aa),minval(bb),minval(cc) )
write(*,*) ’Наибольший из минимальных:’
write(*,*) ’max(minval(aa),mixval(bb),minval(cc))=’,
>
max(minval(aa),minval(bb),minval(cc) )
write(*,*) ’Наименьший из максимальных:’
write(*,*) ’min(maxval(aa),maxval(bb),maxval(cc))=’,
>
min(maxval(aa),maxval(bb),maxval(cc) )
end program minmax max(a,b,c)=
6
min(a,b,c)=
-3
aa:
1 2
3
bb:
-9 3
7
-10
cc:
0 1
2 3
4
maxval(aa)=
3
Наибольший из максимальных:
max(maxval(aa),maxval(bb),maxval(cc))=
7
minval(aa)=
1
Наименьший из минимальных:
min(minval(aa),minval(bb),minval(cc))=
-10
Наибольший из минимальных:
max(minval(aa),mixval(bb),minval(cc))=
1
Наименьший из максимальных:
min(maxval(aa),maxval(bb),maxval(cc))=
3 400

14.12
Примеры работы функции mod
Функция mod(a,p) находит остаток от деления a на p, т.е.
mod(a,p)= a-int(a/p)*p
Например, при аргументах a и p типа integer получаем:
a b
mod(a,p)= a-int(a/p)*p
17 3
17-int(17 / 3 )* 3= 17 - 5 * 3 = 2
-17 3
-17-int((-17)/ 3 )* 3=-17 -(-5)* 3 =-17+15=-2 17
-3 17-int( 17 /(-3))*(-3)=17-(-5)*(-3)=17-15=2
-17 -3 -17-int((-17)/(-3))*(-3)=-17-5*(-3)=-17+15=-2
В случае аргументов типа real таблица выглядит так:
a b
mod(a,p)= a-int(a/p)*p
17.5 5.5 17.5-int( 17.5 / 5.5 )* 5.5 = 17.5 - 3 * 5.5 = 1.0
-17.5 5.5
-17.5-int((-17.5)/ 5.5 )* 5.5 =-17.5-(-3)* 5.5 =-17.5+16.5=-1.0 17.5
-5.5 17.5-int( 17.5 /(-5.5))*(-5.5)=17.5-(-3)*(-5.5)=17.5-16.5=1.0
-17.5
-5.5
-17.5-int((-17.5)/(-5.5))*(-5.5)=-17.5-(-3)*(-5.5)=-17.5+16.5=-1.0
program ts_mod implicit none integer a,
p real s,
t a= 17; p= 3; write(*,’("mod(",i3,",",i2,")=",i5,i5)’)&
& a,p,mod(a,p),a-int(a/p)*p a=-17; p= 3; write(*,’("mod(",i3,",",i2,")=",i5,i5)’)&
& a,p,mod(a,p),a-int(a/p)*p a= 17; p=-3; write(*,’("mod(",i3,",",i2,")=",i5,i5)’)&
& a,p,mod(a,p),a-int(a/p)*p a=-17; p=-3; write(*,’("mod(",i3,",",i2,")=",i5,i5)’)&
& a,p,mod(a,p),a-int(a/p)*p
!
s=
17.5; t= 5.5; write(*,*) ’mod(s,t)=’, mod(s,t), s-int(s/t)*t s= -17.5; t= 5.5; write(*,*) ’mod(s,t)=’, mod(s,t), s-int(s/t)*t s=
17.5; t=-5.5; write(*,*) ’mod(s,t)=’, mod(s,t), s-int(s/t)*t s= -17.5; t=-5.5; write(*,*) ’mod(s,t)=’, mod(s,t), s-int(s/t)*t end program ts_mod mod( 17, 3)=
2 2
mod(-17, 3)=
-2
-2
mod( 17,-3)=
2 2
mod(-17,-3)=
-2
-2
mod(s,t)=
1.0000000 1.0000000
mod(s,t)=
-1.0000000
-1.0000000
mod(s,t)=
1.0000000 1.0000000
mod(s,t)=
-1.0000000
-1.0000000 401


14.13
Примеры работы функции modulo
Функция modulo(a,p) находит такой остаток от деления a на p, когда за результат деления принимается наибольшее целое меньшее или равное аргументу.
modulo(a,p)= a-floor(real(a)/real(p))*p
Часто функцию modulo называют функция по модулю.
Например, для аргументов 17 и 3 типа integer получаем:
a b
modulo(a,p)= a-floor(real(a),real(p))*p
17 3
17 - floor( 17.0 / 3.0) * 3 = 17 - 5 * 3 = 2
-17 3
-17 - floor(-17.0 / 3.0) * 3 =-17 -(-5)* 3 =-17+15=-2 17
-3 17 - floor( 17.0 /(-3.0)) *(-3)= 17-(-5)*(-3)=17-15=2
-17
-3
-17 - floor((-17.0)/(-3.0)) *(-3)=-17-5*(-3)=-17+15=-2
program ts_modulo; implicit none; integer a,
p; real s,
t a= 17; p= 3; write(*,*) ’modulo(a,p)=’,modulo(a,p),a-floor(real(a)/real(p))*p a=-17; p= 3; write(*,*) ’modulo(a,p)=’,modulo(a,p),a-floor(real(a)/real(p))*p a= 17; p=-3; write(*,*) ’modulo(a,p)=’,modulo(a,p),a-floor(real(a)/real(p))*p a=-17; p=-3; write(*,*) ’modulo(a,p)=’,modulo(a,p),a-floor(real(a)/real(p))*p s= 17.0; t= 3.0; write(*,*) ’modulo(s,t)=’, modulo(s,t), s-floor(s/t)*t s=-17.0; t= 3.0; write(*,*) ’modulo(s,t)=’, modulo(s,t), s-floor(s/t)*t s= 17.0; t=-3.0; write(*,*) ’modulo(s,t)=’, modulo(s,t), s-floor(s/t)*t s=-17.0; t=-3.0; write(*,*) ’modulo(s,t)=’, modulo(s,t), s-floor(s/t)*t write(*,*) ’modulo( 8, 5)=’,modulo( 8, 5);
write(*,*) ’modulo(-8, 5)=’,modulo(-8, 5)
write(*,*) ’modulo( 8,-5)=’,modulo( 8,-5)
write(*,*) ’modulo(-8,-5)=’,modulo(-8,-5)
write(*,*) ’modulo( 7.285, 2.35)=’,modulo( 7.285, 2.35)
write(*,*) ’modulo(-7.285, 2.35)=’,modulo(-7.285, 2.35)
write(*,*) ’modulo( 7.285,-2.35)=’,modulo( 7.285,-2.35)
write(*,*) ’modulo(-7.285,-2.35)=’,modulo(-7.285,-2.35)
end program ts_modulo modulo(a,p)=
2 2
modulo(a,p)=
1 1
modulo(a,p)=
-1
-1
modulo(a,p)=
-2
-2
modulo(s,t)=
2.0000000 2.0000000
modulo(s,t)=
1.0000000 1.0000000
modulo(s,t)=
-1.0000000
-1.0000000
modulo(s,t)=
-2.0000000
-2.0000000
modulo( 8, 5)=
3
modulo(-8, 5)=
2
modulo( 8,-5)=
-2
modulo(-8,-5)=
-3 402
modulo( 7.285, 2.35)=
0.23500013
modulo(-7.285, 2.35)=
2.1149998
modulo( 7.285,-2.35)=
-2.1149998
modulo(-7.285,-2.35)= -0.23500013 14.14
Примеры работы функции sign program ts_sign implicit none integer j real a, b a=5.3
do j=-2,2
b=j write(*,’("sign(",f5.2,",",f5.2,")=",f5.2)’) a, b,
sign(a,b)
enddo a=-5.3
do j=-2,2
b=j write(*,’("sign(",f5.2,",",f5.2,")=",f5.2)’) a, b,
sign(a,b)
enddo end program ts_sign sign( 5.30,-2.00)=-5.30
sign( 5.30,-1.00)=-5.30
sign( 5.30, 0.00)= 5.30
sign( 5.30, 1.00)= 5.30
sign( 5.30, 2.00)= 5.30
sign(-5.30,-2.00)=-5.30
sign(-5.30,-1.00)=-5.30
sign(-5.30, 0.00)= 5.30
sign(-5.30, 1.00)= 5.30
sign(-5.30, 2.00)= 5.30 403

15
Приложение VI. Функции запроса характеристик представления числовых данных
Функции запроса (см. [2]) — это запросы к окружению о характери- стиках представления данных, зависящих от реализации. В качестве ар- гумента функции используют имена переменных или констант, однако результат работы зависит не от значения аргумента x, а от его типа и параметра разновидности типа. Обозначения и формулы, используемые в разделе 12.10.5 книги [2].
• b — основание системы счисления для вещественных чисел r — основание системы счисления для целых чисел;
Любое из них можно получить встроенной фукцией radix(x).
• q — количество значащих цифр в модельном представлении целого;
p — количество значащих цифр в модельном представлении веще- ственного;
Любое из них можно получить встроенной фукцией digit(x).
• b
1−p
— результат работы функции epsilon(x)
• e max
— максимальный порядок (показатель степени основания); на- ходится встроенной функцией maxexponent(x)
e min
— минимальный порядок (показатель степени основания); на- ходится встроенной функцией minexponent(x)
• r q
− 1 — наибольшее целое в модельном представлении целого;
(1 − b
−p
) ∗ b e
max
— наибольшее вещественное в модельном пред- ставлении вещественного;
Любое из них можно получить встроенной фукцией huge(x).
Наименьшее положительное число в модельном представлении ве- щественного данного можно получить функцией tiny(x).
Десятичную точность модели и наибольший десятичный порядок данно- го той же разновидности типа, что и аргумент x, находятся посредством функций precision(x) и range(x) соответственно
Функция bit_size(i) находит число битов в модели данных той же разновидности целого типа, что и аргумент i.
404


15.1
Функция radix(x)
— возвращает значение типа integer равное основанию системы счисле- ния, используемой для представления чисел того же типа, что и аргумент x (integer или real).
program test_radix; implicit none; real(4)
x4; real(8)
x8; real(10) xd real(16) xh write(*,*) ’По умолчанию для типа integer основание = radix( 1 )=’,radix( 1 );
write(*,*) ’По умолчанию для типа real основание = radix(1.3)=’,radix(1.3);
write(*,*) ’radix(x4)=’,radix(x4),’
radix(1.3_4 )=’,radix(1.3_4)
write(*,*) ’radix(x8)=’,radix(x8),’
radix(1.3_8 )=’,radix(1.3_8)
write(*,*) ’radix(xd)=’,radix(xd),’
radix(1.3_10)=’,radix(1.3_10)
write(*,*) ’radix(xh)=’,radix(xh),’
radix(1.3_16)=’,radix(1.3_16)
end
По умолчанию для типа integer основание = radix( 1 )=
2
По умолчанию для типа real основание = radix(1.3)=
2
radix(x4)=
2
radix(1.3_4 )=
2
radix(x8)=
2
radix(1.3_8 )=
2
radix(xd)=
2
radix(1.3_10)=
2
radix(xh)=
2
radix(1.3_16)=
2 405

15.2
Функция digits(x)
program test_digits; implicit none; character(14) sf integer i real r real(4) r4;
real(8) r8; real(10) rx;
! real(16) rh integer(1) i1; integer(2) i2; integer(4) i4; integer(8) i8; ! integer(16) ih write(*,*) ’ По умолчанию:’
write(*,’(13x,a,i3)’) ’
digits( i )=’, digits( i )
write(*,’(13x,a,i3)’) ’
digits( r )=’, digits( r )
sf=’(a,i3,3x,a,i3)’
write(*,’(/a)’) ’ INTEGER(...) при явном описании типа:’
write(*,sf) ’digits(i1)=’,digits(i1),’digits( 1_1 )=’,digits(1_1)
write(*,sf) ’digits(i2)=’,digits(i2),’
digits( 1_2 )=’,digits(1_2)
write(*,sf) ’digits(i4)=’,digits(i4),’
digits( 1_4 )=’,digits(1_4)
write(*,sf) ’digits(i8)=’,digits(i8),’
digits( 1_8 )=’,digits(1_8)
write(*,sf) ’digits(ih)=’,digits(i8),’
digits( 1_16)=’,digits(1_8)
write(*,’(/a)’) ’
REAL(...) при явном описании типа:’
write(*,sf) ’digits(r4)=’,digits(r4),’
digits(1.3_4 )=’,digits(1.3_4)
write(*,sf) ’digits(r8)=’,digits(r8),’
digits(1.3_8 )=’,digits(1.3_8)
write(*,sf) ’digits(rx)=’,digits(rx),’
digits(1.3_10)=’,digits(1.3_10)
!write(*,sf) ’digits(rh)=’,digits(rh),’
digits(1.3_16)=’,digits(1.3_16)
end
По умолчанию:
digits( i )= 31

0>
1   ...   15   16   17   18   19   20   21   22   23

! Почему не 32 ?
digits( r )= 24

! Почему не 32 ?
INTEGER(...) при явном описании типа:
digits(i1)=
7
digits( 1_1 )=
7
! Почему не
8 ?
digits(i2)= 15
digits( 1_2 )= 15
! Почему не
16 ?
digits(i4)= 31
digits( 1_4 )= 31
! Почему не
32 ?
digits(i8)= 63
digits( 1_8 )= 63
! Почему не
64 ?
digits(ih)=127
digits( 1_16)=127

! Почему не 128.?
REAL(...) при явном описании типа:
digits(r4)= 24
digits(1.3_4 )= 24
! Почему не
32 ?
digits(r8)= 53
digits(1.3_8 )= 53
! Почему не
64 ?
digits(rx)= 64
digits(1.3_10)= 64
! Почему не
64 ?
digits(rh)=113
digits(1.3_16)=113

! Почему не 128 ?
406

15.3
Функция epsilon(x)
— возвращает значение b
1−p
(самая младшая степень двойки в пределах разрядной сетки соответствующей вещественной единицы):
1+epsilon(x)>1, но 1+epsilon(x)/2==1.
Тип и параметр типа значения epsilon(x) такие же как у x.
program ts_epsilon; implicit none;
character(27), parameter :: sf(4)=(/’(i3,e26.8 ,i4,e26.8 ,l5,l8)’,&
&
’(i3,e26.16,i4,e26.16,l5,l8)’,&
&
’(i3,e26.19,i4,e26.19,l5,l8)’,&
&
’(i3,e26.19,i4,e26.19,l5,l8)’/)
real( 4) r4,e4; real(8) r8,e8; real(10) rX,ex; real(16) rH,eH
integer p4, p8, pX, pH
p4= digits(r4);
p8= digits(r8);
pX= digits(rX); pH= digits(rH)
e4=epsilon(r4);
e8=epsilon(r8);
eX=epsilon(rX); eH=epsilon(rH)
write(*,*) ’k=4, 8, 10, 16 - параметр разновидности данного типа REAL’
write(*,’(" p=digits(r) - число битов для модели мантиссы REAL(k)")’)
write(*,’(78("-"))’)
write(*,’(2x,"k",12x,"epsilon",10x,"p",8x,"2.0_k**(1-p)",7x,&
&
"1+e/=1",2x,"1+e/2==1")’)
write(*,’(78("-"))’)
write(*,sf(1)) kind(e4), e4,p4, 2.0**(1-p4),
1+e4/=1, 1+e4/2==1
write(*,sf(2)) kind(e8), e8,p8, 2.0_8**(1-p8),
1+e4/=1, 1+e8/2==1
write(*,sf(3)) kind(eX), eX,pX, 2.0_10**(1-pX), 1+e4/=1, 1+eX/2==1
write(*,sf(4)) kind(eH), eH,pH, 2.0_10**(1-pH), 1+e4/=1, 1+eH/2==1
stop 0
end program ts_epsilon k=4, 8, 10, 16 - ппараметр разновидности данного типа REAL
p=digits(r) - число битов для модели мантиссы REAL(k)
------------------------------------------------------------------------------ k
epsilon p
2.0_k**(1-p)
1+e/=1 1+e/2==1
------------------------------------------------------------------------------
4 0.11920929E-06 24 0.11920929E-06
T
T
8 0.2220446049250313E-15 53 0.2220446049250313E-15
T
T
10 0.1084202172485504434E-18 64 0.1084202172485504434E-18
T
T
16 0.1925929944387235853E-33 113 0.1925929944387235853E-33
T
T
Так как результат работы epsilon(x) не зависит от величины аргумента,
то не указывая явно параметр разновидности, можно, например, грубо оценить погрешность округления x по формуле abs(x)*epsilon(x);
407

15.4
Функции maxexponent, minexponent
Функции maxexponent(x) и minexponent(x) находят соответственно e
max и e min
(максимальный и минимальный порядки в модели данного того же типа и его параметра разновидности, что и аргумент x). Порядок
— показатель степени основания b, которое обычно равно 2.
program ts_maxminexp; implicit none real(4) e, b; real(8) e8; real(10) eX; real(16) eH
integer(4) m, p;
m=maxexponent(e); write(*,’(" maxexponent(e)=",i5)’) m p=digits(e);
write(*,’("p=digits(e)=", i5
)’) p b= radix(e);
write(*,’("b= radix(e)=",e15.7)’) b e=2**m;
write(*,’(20x,a,e15.7)’) ’e=2**m=’,e e=b**m;
write(*,’(16x,a,e15.7)’) ’e=2.0_4**m=’,e e=b**(m-1);
write(*,’(12x,a,e15.7)’)
’e=2.0_4**(m-1)=’,e e=2*(1-b**(-p))*b**(m-1);
write(*,’(2x,a,e15.7)’) ’e=2*(1-b**(-p))*b**(m-1)=’,e write(*,’(15x,a,e15.7)’) ’huge(1.0_4)=’, huge(1.0_4)
m=minexponent(e); write(*,’(" minexponent(e)=",i5)’) m e=2**m;
write(*,’(20x,a,e15.7)’) ’e=2**m=’,e e=b**m;
write(*,’(16x,a,e15.7)’) ’e=2.0_4**m=’,e e=b**(m-1);
write(*,’(12x,a,e15.7)’)
’e=2.0_4**(m-1)=’,e write(*,’(19x,a,e15.7)’) ’tiny(e)=’, tiny(e)
write(*,’("x",6x,"maxexponent(x)",3x,"minexponent(x)")’)
write(*,’(a,2i15)’) ’e8’, maxexponent(e8), minexponent(e8)
write(*,’(a,2i15)’) ’eX’, maxexponent(eX), minexponent(eX)
write(*,’(a,2i15)’) ’eH’, maxexponent(eX), minexponent(eH)
end program ts_maxminexp maxexponent(e)=
128
p=digits(e)=
24
b= radix(e)=
0.2000000E+01
e=2**m=
0.0000000E+00
e=2.0_4**m=
Infinity e=2.0_4**(m-1)=
0.1701412E+39
e=2*(1-b**(-p))*b**(m-1)=
0.3402823E+39
huge(1.0_4)=
0.3402823E+39
minexponent(e)= -125
e=2**m=
0.0000000E+00
e=2.0_4**m=
0.2350989E-37
e=2.0_4**(m-1)=
0.1175494E-37
tiny(e)=
0.1175494E-37
x maxexponent(x)
minexponent(x)
e8 1024
-1021
eX
16384
-16381
eH
16384
-16381 408


15.5
Функция tiny
Функция tiny находит наименьшее положительное число в модели дан- ного того же типа и параметра разновидности, что и аргумент
Программа ts_tiny демонстрирует работу пользовательской функ- ции tiny_my, которая, используя minexponent(x), вычисляет то же,
что и встроенная tiny.
module tinymy implicit none interface tiny_my module procedure tiny4, tiny8, tinyX, tinyH
end interface tiny_my contains function tiny4(x) result(w); real(4) x, w; w= 2.0**(minexponent(x)-1)
end function tiny4
function tiny8(x) result(w); real(8) x, w; w= 2.0_8**(minexponent(x)-1)
end function tiny8
function tinyX(x) result(w); real(10) x, w; w= 2.0_10**(minexponent(x)-1)
end function tinyX
function tinyH(x) result(w); real(16) x, w; w= 2.0_16**(minexponent(x)-1)
end function tinyH
end module tinymy program ts_tiny use tinymy implicit none integer(4) m, p real(4) e, b write(*,’(8x,"x",17x,"tiny(x)",14x,"tiny_my(x)")’)
write(*,’(e15.7,2(e24.7,2x))’)
0.0 ,
tiny(0.0_4), tiny_my(0.0_4)
write(*,’(e15.7,2(e25.16e3,2X))’) -1._8,
tiny(-1._8), tiny_my(-1._8)
write(*,’(e15.7,2(e26.16e4,1x))’)
3.7_10, tiny(3.7_10), tiny_my(3.7_10)
write(*,’(e15.7,2(e27.16e5))’)
8e9_16, tiny(8e9_16), tiny_my(8e9_16)
stop 0
end program ts_tiny x
tiny(x)
tiny_my(x)
0.0000000E+00 0.1175494E-37 0.1175494E-37
-0.1000000E+01 0.2225073858507201E-307 0.2225073858507201E-307 0.3700000E+01 0.3362103143112094E-4931 0.3362103143112094E-4931 0.8000000E+10 0.3362103143112094E-04931 0.3362103143112094E-04931 409

15.6
Функция huge(x)
huge(x) — наибольшее число в модели того же типа и того же параметра разновидности, что и аргумент.
15.6.1
Семейство integer
Если для расчёта huge(i) (когда i — целое) воспользоваться непосред- ственно формулами q = digits(i); h = 2
q
− 1,
то можно обнаружить забавные эффекты конечнозначной целочислен- ной арифметики. Полезно проанализировать результаты работы program ts_hugeint implicit none integer(1) i1
integer(2) i2
integer(4) i4, q1, h1, q2, h2, q4, h4, w4, q8, h8, w8
integer(8) i8, qo, ho q1=digits(i1)
q2=digits(i2)
q4=digits(i4)
q8=digits(i8)
write(*,’("
q1=digits(i1)=",i4,";
2**",i2,"=",i11)’) q1,q1,2**q1
write(*,’("
q2=digits(i2)=",i4,";
2**",i2,"=",i11)’) q2,q2,2**q2
write(*,’("
q4=digits(i4)=",i4,";
2**",i2,"=",i11)’) q4,q4,2**q4
write(*,’("
q8=digits(i8)=",i4,";
2**",i2,"=",i11)’) q8,q8,2**q8
write(*,*)
write(*,’(" Почему расчёт 2**7 и 2**15 верен, а 2**31 и 2**63 ошибочен?")’)
h1= 2**q1-1
h2= 2**q2-1
h4= 2**q4-1
h8= 2**q8-1
write(*,’("huge(i1)=",i10,"=2**q1-1=",i10)’) huge(i1), h1
write(*,’("huge(i2)=",i10,"=2**q2-1=",i10)’) huge(i2), h2
write(*,’("huge(i4)=",i10,"=2**q4-1=",i10)’) huge(i4), h4
write(*,*)
write(*,’(a,i11,3x,a,i11,3x,a,i11)’) ’2**q4=’,2**q4,&
& ’
2**q4-1=’,2**q4-1,&
&’ 2*(2**(q4-1)-1)+1=’,2*(2**(q4-1)-1)+1
write(*,’(" Почему, -2147483648-1=+2147483647?"/)’)
410
write(*,’(70("="))’)
w4=2**q4; write(*,’(a,b32.32)’)

2**q4=’,w4
write(*,’(a,b32.32)’)
’вычитаем
1=’,1
write(*,’(12x,32("-"))’)
write(*,’(a,b32.32)’) ’
2**q4-1=’,h4
write(*,’(70("."))’)
w4=2**(q4-1); write(*,’(12x,a,b32.32)’) ’
2**(q4-1)=’,w4
w4=w4-1;
write(*,’(12x,a,b32.32)’) ’вычитаем
1=’,1
write(*,’(24x,32("-"))’)
write(*,’(9x,a,b32.32)’) ’
2**(q4-1)-1=’,w4
w4=2*w4; write(*,’(10x,a,b32)’) ’умножаем на 2=’,2
write(*,’(24x,32("-"))’)
write(*,’(4x,a,b32.32)’)

2(2**(q4-1)-1)=’,w4
write(*,’(10x,a,b32.32)’) ’прибавляем
1=’,1
w4=w4+1; write(*,’(24x,32("-"))’)
write(*,’(2x,a,b32.32)’) ’
2(2**(q4-1)-1_1)+1=’,w4
write(*,’(70("="))’)
write(*,’("HUGE от целого аргумента")’)
write(*,’(" kind(i)",3x,"digits(i)",11x,"huge(i)",9x,&
&"2*(2**(digits(i)-1)+1")’)
write(*,’(4x,i1,i11,i28,i23)’) kind(i1), digits(i1), huge(i1), h1
write(*,’(4x,i1,i11,i28,i23)’) kind(i2), digits(i2), huge(i2), h2
write(*,’(4x,i1,i11,i28,i23)’) kind(i4), digits(i4), huge(i4), h4
write(*,’(4x,i1,i11,i28,i23)’) kind(i8), digits(i8), huge(i8), h8
write(*,’(70("="))’)
write(*,*)
write(*,’(" Почему результаты расчёта одного и того же по формуле 2**q8-1"/&
&" и по huge(i8) различны, хотя, на первый взгляд, должны быть одинаковы?")’)
qo=q8
write(*,*) ’ q8=’,q8
write(*,*) ’ qo=’,qo write(*,’("2*(2**(q8-1)-1)+1=",i30)’) 2*(2**(q8-1)-1)+1
write(*,’("2*(2**(qo-1)-1)+1=",i30)’) 2*(2**(qo-1)-1)+1
write(*,’("2**qo=",b64.64)’) 2**qo write(*,’("2**qo=",i21)’) 2**qo end program ts_hugeint
411