update file date
This commit is contained in:
398
20210513-第11章习题.f90
Normal file
398
20210513-第11章习题.f90
Normal file
@ -0,0 +1,398 @@
|
||||
! ==============================================================================
|
||||
! 通过 gfortran ./test.f90 -o ./run && ./run 运行
|
||||
! 程序名:
|
||||
! 第11章习题
|
||||
! 目的:
|
||||
!
|
||||
! 修订记录:
|
||||
! 日期 编程者 改动描述
|
||||
! =================== ============= =====================================
|
||||
! 2021-05-13 14:32:35 Sola 习题11-5 判断格式是否正确
|
||||
! 2021-05-13 15:42:31 Sola 习题11-6 函数的导数
|
||||
! 2021-05-13 17:17:22 Sola 习题11-7 经时计算,判断单精度和双精度时间
|
||||
! 2021-05-14 19:19:29 Sola 习题11-8 跳过,习题11-9 复数计算
|
||||
! 2021-05-14 19:56:11 Sola 习题11-10 复数的振幅和相位
|
||||
! 2021-05-14 20:09:50 Sola 习题11-11 欧拉公式
|
||||
! 程序结构:
|
||||
!
|
||||
! ==============================================================================
|
||||
! 模块:
|
||||
module Chapter11
|
||||
implicit none
|
||||
! 数据字典
|
||||
! 声明常数
|
||||
REAL, PARAMETER :: PI=3.14159265 ! PI值
|
||||
REAL, PARAMETER :: e=2.718281828459 ! 自然对数
|
||||
INTEGER, PARAMETER :: arrayLength=20 ! 数组基准长度
|
||||
! 声明变量
|
||||
! 创建显式接口
|
||||
contains
|
||||
! subroutine SubName(varName1,varName2)
|
||||
! implicit none
|
||||
! ! 数据字典
|
||||
! end subroutine SubName
|
||||
end module Chapter11
|
||||
! ==============================================================================
|
||||
! 主程序:
|
||||
program ProName
|
||||
implicit none
|
||||
! 数据字典
|
||||
! 声明常量
|
||||
! 声明变量
|
||||
! 变量初始化
|
||||
! 数据输入
|
||||
! 运算过程
|
||||
! 结果输出
|
||||
! call Exercises11_5
|
||||
! call Exercises11_6
|
||||
! call Exercises11_7
|
||||
! call Exercises11_9
|
||||
! call Exercises11_10
|
||||
call Exercises11_11
|
||||
end program ProName
|
||||
! ==============================================================================
|
||||
! 子程序
|
||||
! subroutine SubName(varName1,varName2)
|
||||
! use MouName
|
||||
! implicit none
|
||||
! Type, intent(inout) :: varName
|
||||
! end subroutine SubName
|
||||
! ==============================================================================
|
||||
! 函数
|
||||
! function FunName(varName1,varName2)
|
||||
! use MouName
|
||||
! implicit none
|
||||
! end function FunName
|
||||
! ==============================================================================
|
||||
! 习题11-5
|
||||
subroutine Exercises11_5
|
||||
implicit none
|
||||
call Suba
|
||||
! call Subb
|
||||
contains
|
||||
subroutine Suba
|
||||
integer, parameter :: sgl = kind(0.0)
|
||||
integer, parameter :: dbl = kind(0.0D0)
|
||||
real(kind=sgl) :: a
|
||||
real(kind=dbl) :: b
|
||||
integer :: i
|
||||
integer :: errorLevel
|
||||
open(unit=1, status='scratch', iostat=errorLevel)
|
||||
if ( errorLevel /= 0 ) stop ""
|
||||
write(*, *) sgl, dbl
|
||||
do i = 1, 45
|
||||
write(*, *) i, selected_real_kind(r=i)
|
||||
end do
|
||||
write(1, '(A)') &
|
||||
&"111111111111111111111111111111111111111111111", &
|
||||
&"222222222222222222222222222222222222222222222"
|
||||
rewind(unit=1, iostat=errorLevel)
|
||||
if ( errorLevel /= 0 ) stop ""
|
||||
read(1, '(F16.2)') a, b
|
||||
write(*, *) a, b
|
||||
end subroutine Suba
|
||||
! subroutine Subb
|
||||
! end subroutine Subb
|
||||
end subroutine Exercises11_5
|
||||
! 习题11-6 函数的导数
|
||||
subroutine Exercises11_6
|
||||
implicit none
|
||||
integer, parameter :: realType = selected_real_kind(p=13) ! 确认实数类型
|
||||
real(realType) :: x0, dx ! 待测点, 步长
|
||||
real(realType) :: derivationX0 ! 导数值
|
||||
real(realType), external :: Fx ! 外部函数
|
||||
x0 = 0._realType ! 变量初始化
|
||||
dx = 0.01_realType
|
||||
call Derivation(Fx, x0, dx, derivationX0) ! 计算导数
|
||||
write(*, *) '函数在0处的值为', Fx(0._realType), '在0处的导数值为', derivationX0 ! 输出结果
|
||||
contains
|
||||
subroutine Derivation(inputFunction, x0, dx, derivationX0)
|
||||
integer, parameter :: realType = selected_real_kind(p=13) ! 确认实数类型
|
||||
real(realType), intent(in) :: x0, dx ! 输入点位及步长
|
||||
real(realType), intent(out) :: derivationX0 ! 输出的导数值
|
||||
real(realType), external :: inputFunction ! 外部函数
|
||||
derivationX0 = (inputFunction(x0 + dx) - inputFunction(x0))/dx ! 计算导数值
|
||||
end subroutine Derivation
|
||||
end subroutine Exercises11_6
|
||||
function Fx(x)
|
||||
implicit none
|
||||
integer, parameter :: realType = selected_real_kind(p=13) ! 确认实数类型
|
||||
real(realType), intent(in) :: x ! 输入点位
|
||||
real(realType) :: Fx ! 定义函数输出类型
|
||||
Fx = 10._realType*sin(20._realType*x) ! 计算函数值
|
||||
end function Fx
|
||||
! 习题11-7 经时计算 不过话说回来,现在的编译器在这边好像还是有优化的,,,结果可能不太准
|
||||
subroutine Exercises11_7
|
||||
implicit none
|
||||
integer, parameter :: dbl = selected_real_kind(p=13)
|
||||
integer, parameter :: sgl = selected_real_kind(p=1)
|
||||
real(dbl), dimension(10, 10) :: matrix
|
||||
real(dbl), dimension(10) :: arrayX
|
||||
real(sgl), dimension(10, 10) :: matrix1
|
||||
real(sgl), dimension(10) :: arrayX1
|
||||
integer, dimension(8) :: timeNow
|
||||
real :: timePast
|
||||
integer, dimension(8) :: timeOld
|
||||
integer :: errorLevel
|
||||
integer :: i
|
||||
open(unit=1, status='scratch', iostat=errorLevel)
|
||||
if ( errorLevel /= 0 ) stop ""
|
||||
write(1, '(A)') &
|
||||
&" -2., 5., 1., 3., 4. -1., -2., -1., -5., -2.", &
|
||||
&" 6., 4., -1., 6., -4., -5., 3., -1., 4., 3.", &
|
||||
&" -6., -5., -2., -2., -3., 6., 4., 2., -6., 4.", &
|
||||
&" 2., 4., 4., 4., 5., -4., 0., 0., -4., 6.", &
|
||||
&" -4., -1., 3., -3., -4., -4., -4., 4., 3., -3.", &
|
||||
&" 4., 3., 5., 1., 1., 1., 0., 3., 3., 6.", &
|
||||
&" 1., 2., -2., 0., 3., -5., 5., 0., 1., -4.", &
|
||||
&" -3., -4., 2., -1., -2., 5., -1., -1., -4., 1.", &
|
||||
&" 5., 5., -2., -5., 1., -4., -1., 0., -2., -3.", &
|
||||
&" -5., -2., -5., 2., -1., 3., -1., 1., -4., 4."
|
||||
rewind(unit=1, iostat=errorLevel)
|
||||
if ( errorLevel /= 0 ) stop ""
|
||||
arrayX = (/ -5., -6., -7., 0., 5., -8., 1., -4., -7., 6./)
|
||||
read(1, *) (matrix(i, :), i = 1, 10)
|
||||
rewind(unit=1, iostat=errorLevel)
|
||||
if ( errorLevel /= 0 ) stop ""
|
||||
arrayX1 = (/ -5., -6., -7., 0., 5., -8., 1., -4., -7., 6./)
|
||||
read(1, *) (matrix1(i, :), i = 1, 10)
|
||||
call set_timer
|
||||
do i = 1, 1000000
|
||||
call GAEli1(matrix1, arrayX1, errorLevel)
|
||||
! arrayX1 = (/ -5., -6., -7., 0., 5., -8., 1., -4., -7., 6./)
|
||||
end do
|
||||
call elapsed_time(timePast)
|
||||
write(*, *) '使用单精度计算消耗时间', timePast, 's'
|
||||
call set_timer
|
||||
do i = 1, 1000000
|
||||
call GAEli2(matrix, arrayX, errorLevel)
|
||||
! arrayX = (/ -5., -6., -7., 0., 5., -8., 1., -4., -7., 6./)
|
||||
end do
|
||||
call elapsed_time(timePast)
|
||||
write(*, *) '使用双精度计算消耗时间', timePast, 's'
|
||||
contains
|
||||
! 解方程子程序
|
||||
! 经时子程序
|
||||
subroutine set_timer ! 创建子程序1
|
||||
call DATE_AND_TIME(values=timeNow) ! 调用当前时间子程序
|
||||
end subroutine set_timer ! 结束子程序1
|
||||
subroutine elapsed_time(timePast) ! 创建子程序2
|
||||
real, intent(out) :: timePast ! 定义输出变量
|
||||
timeOld = timeNow ! 传递值
|
||||
call set_timer ! 调用子程序1
|
||||
timePast = ((real(timeNow(3)-timeOld(3))*24 + real(timeNow(5)-timeOld(5)))&
|
||||
&*60 + real(timeNow(6)-timeOld(6)))*60 + real(timeNow(7)-timeOld(7)) + &
|
||||
&real(timeNow(8)-timeOld(8))/1000 ! 计算经历时间(秒)
|
||||
end subroutine elapsed_time ! 结束子程序2
|
||||
! 高斯-亚当消元法,不破坏输入矩阵
|
||||
subroutine GAEli1(matrixInput1, arrayX, errorLevel)
|
||||
integer, parameter :: varKind = selected_real_kind(p=2)
|
||||
real(varKind), dimension(:, :), intent(inout) :: matrixInput1 ! 输入矩阵(输入)
|
||||
real(varKind), dimension(size(matrixInput1, 1), size(matrixInput1, 2)) :: matrixInput
|
||||
! 运算矩阵
|
||||
real(varKind), dimension(:), intent(inout) :: arrayX ! 输入常数向量, 输出X解向量
|
||||
integer, intent(out) :: errorLevel ! 错误值
|
||||
real(varKind) :: temp ! 临时值, 用于数值交换
|
||||
integer :: maxLocate ! 最大值所在行
|
||||
integer :: i, n, m ! 局部变量: 循环参数
|
||||
matrixInput = matrixInput1
|
||||
m = size(matrixInput, 1)
|
||||
do n = 1, m
|
||||
maxLocate = n ! 初始化绝对值最大的位置
|
||||
do i = n+1, m ! 执行最大支点技术,减少舍入误差
|
||||
if ( abs(matrixInput(i, n)) > abs(matrixInput(maxLocate, n)) ) then
|
||||
maxLocate = i
|
||||
end if
|
||||
end do
|
||||
if ( abs(matrixInput(maxLocate, n)) < 1.0E-30 ) then
|
||||
errorLevel = 1 ! 如果绝对值最大为0, 则矩阵不满秩, 无解
|
||||
return ! 退出运算
|
||||
end if
|
||||
if ( maxLocate /= n ) then ! 如果绝对值最大值位置发生了变化, 则交换
|
||||
do i = 1, m
|
||||
temp = matrixInput(maxLocate, i)
|
||||
matrixInput(maxLocate, i) = matrixInput(n, i)
|
||||
matrixInput(n, i) = temp
|
||||
end do
|
||||
temp = arrayX(maxLocate)
|
||||
arrayX(maxLocate) = arrayX(n)
|
||||
arrayX(n) = temp
|
||||
end if
|
||||
do i = 1, m ! 消去其他行所有第n列的系数
|
||||
if ( i /= n ) then
|
||||
temp = -matrixInput(i, n)/matrixInput(n, n) ! 这里务必要设置一个临时值保存数值, 不然会被修改
|
||||
matrixInput(i, :) = matrixInput(i, :) + matrixInput(n, :)*temp
|
||||
arrayX(i) = arrayX(i) + arrayX(n)*temp
|
||||
end if
|
||||
end do
|
||||
end do
|
||||
do i = 1, m ! 产生X的解向量
|
||||
arrayX(i) = arrayX(i)/matrixInput(i, i)
|
||||
matrixInput(i, i) = 1.
|
||||
end do
|
||||
errorLevel = 0
|
||||
end subroutine GAEli1
|
||||
subroutine GAEli2(matrixInput1, arrayX, errorLevel)
|
||||
integer, parameter :: varKind = selected_real_kind(p=13)
|
||||
real(varKind), dimension(:, :), intent(inout) :: matrixInput1 ! 输入矩阵(输入)
|
||||
real(varKind), dimension(size(matrixInput1, 1), size(matrixInput1, 2)) :: matrixInput
|
||||
! 运算矩阵
|
||||
real(varKind), dimension(:), intent(inout) :: arrayX ! 输入常数向量, 输出X解向量
|
||||
integer, intent(out) :: errorLevel ! 错误值
|
||||
real(varKind) :: temp ! 临时值, 用于数值交换
|
||||
integer :: maxLocate ! 最大值所在行
|
||||
integer :: i, n, m ! 局部变量: 循环参数
|
||||
matrixInput = matrixInput1
|
||||
m = size(matrixInput, 1)
|
||||
do n = 1, m
|
||||
maxLocate = n ! 初始化绝对值最大的位置
|
||||
do i = n+1, m ! 执行最大支点技术,减少舍入误差
|
||||
if ( abs(matrixInput(i, n)) > abs(matrixInput(maxLocate, n)) ) then
|
||||
maxLocate = i
|
||||
end if
|
||||
end do
|
||||
if ( abs(matrixInput(maxLocate, n)) < 1.0E-30 ) then
|
||||
errorLevel = 1 ! 如果绝对值最大为0, 则矩阵不满秩, 无解
|
||||
return ! 退出运算
|
||||
end if
|
||||
if ( maxLocate /= n ) then ! 如果绝对值最大值位置发生了变化, 则交换
|
||||
do i = 1, m
|
||||
temp = matrixInput(maxLocate, i)
|
||||
matrixInput(maxLocate, i) = matrixInput(n, i)
|
||||
matrixInput(n, i) = temp
|
||||
end do
|
||||
temp = arrayX(maxLocate)
|
||||
arrayX(maxLocate) = arrayX(n)
|
||||
arrayX(n) = temp
|
||||
end if
|
||||
do i = 1, m ! 消去其他行所有第n列的系数
|
||||
if ( i /= n ) then
|
||||
temp = -matrixInput(i, n)/matrixInput(n, n) ! 这里务必要设置一个临时值保存数值, 不然会被修改
|
||||
matrixInput(i, :) = matrixInput(i, :) + matrixInput(n, :)*temp
|
||||
arrayX(i) = arrayX(i) + arrayX(n)*temp
|
||||
end if
|
||||
end do
|
||||
end do
|
||||
do i = 1, m ! 产生X的解向量
|
||||
arrayX(i) = arrayX(i)/matrixInput(i, i)
|
||||
matrixInput(i, i) = 1.
|
||||
end do
|
||||
errorLevel = 0
|
||||
end subroutine GAEli2
|
||||
end subroutine Exercises11_7
|
||||
! 习题11-9 复数计算
|
||||
subroutine Exercises11_9
|
||||
implicit none
|
||||
integer, parameter :: dbl = selected_real_kind(p=3)
|
||||
complex(dbl), dimension(3, 3) :: matrix
|
||||
complex(dbl), dimension(3) :: arrayX
|
||||
integer :: errorLevel
|
||||
integer :: i
|
||||
open(unit=1, status='scratch', iostat=errorLevel)
|
||||
if ( errorLevel /= 0 ) stop ""
|
||||
write(1, '(A)') &
|
||||
&"( -2., 5.), ( 1., 3.), ( 4., -1.)", &
|
||||
&"( 2., -1.), ( -5., -2.), ( -1., 6.)", &
|
||||
&"( -1., 6.), ( -4., -5.), ( 3., -1.)", &
|
||||
&"( 7., 5.), (-10., -8.), ( -3., -3.)"
|
||||
rewind(unit=1, iostat=errorLevel)
|
||||
if ( errorLevel /= 0 ) stop ""
|
||||
read(1, *) (matrix(i, :), i = 1, 3)
|
||||
read(1, *) arrayX
|
||||
call GAEli(matrix, arrayX, errorLevel)
|
||||
write(*, *) '计算结果为:'
|
||||
write(*, *) 'x1 = ', arrayX(1)
|
||||
write(*, *) 'x2 = ', arrayX(2)
|
||||
write(*, *) 'x3 = ', arrayX(3)
|
||||
contains
|
||||
! 复数求解
|
||||
subroutine GAEli(matrixInput1, arrayX, errorLevel)
|
||||
integer, parameter :: varKind = selected_real_kind(p=3)
|
||||
complex(varKind), dimension(:, :), intent(inout) :: matrixInput1 ! 输入矩阵(输入)
|
||||
complex(varKind), dimension(size(matrixInput1, 1), size(matrixInput1, 2)) :: matrixInput
|
||||
! 运算矩阵
|
||||
complex(varKind), dimension(:), intent(inout) :: arrayX ! 输入常数向量, 输出X解向量
|
||||
integer, intent(out) :: errorLevel ! 错误值
|
||||
complex(varKind) :: temp ! 临时值, 用于数值交换
|
||||
integer :: maxLocate ! 最大值所在行
|
||||
integer :: i, n, m ! 局部变量: 循环参数
|
||||
matrixInput = matrixInput1
|
||||
m = size(matrixInput, 1)
|
||||
do n = 1, m
|
||||
maxLocate = n ! 初始化绝对值最大的位置
|
||||
do i = n+1, m ! 执行最大支点技术,减少舍入误差
|
||||
if ( cabs(matrixInput(i, n)) > cabs(matrixInput(maxLocate, n)) ) then
|
||||
maxLocate = i
|
||||
end if
|
||||
end do
|
||||
if ( cabs(matrixInput(maxLocate, n)) < 1.0E-30 ) then
|
||||
errorLevel = 1 ! 如果绝对值最大为0, 则矩阵不满秩, 无解
|
||||
return ! 退出运算
|
||||
end if
|
||||
if ( maxLocate /= n ) then ! 如果绝对值最大值位置发生了变化, 则交换
|
||||
do i = 1, m
|
||||
temp = matrixInput(maxLocate, i)
|
||||
matrixInput(maxLocate, i) = matrixInput(n, i)
|
||||
matrixInput(n, i) = temp
|
||||
end do
|
||||
temp = arrayX(maxLocate)
|
||||
arrayX(maxLocate) = arrayX(n)
|
||||
arrayX(n) = temp
|
||||
end if
|
||||
do i = 1, m ! 消去其他行所有第n列的系数
|
||||
if ( i /= n ) then
|
||||
temp = -matrixInput(i, n)/matrixInput(n, n) ! 这里务必要设置一个临时值保存数值, 不然会被修改
|
||||
matrixInput(i, :) = matrixInput(i, :) + matrixInput(n, :)*temp
|
||||
arrayX(i) = arrayX(i) + arrayX(n)*temp
|
||||
end if
|
||||
end do
|
||||
end do
|
||||
do i = 1, m ! 产生X的解向量
|
||||
arrayX(i) = arrayX(i)/matrixInput(i, i)
|
||||
matrixInput(i, i) = 1.
|
||||
end do
|
||||
errorLevel = 0
|
||||
end subroutine GAEli
|
||||
end subroutine Exercises11_9
|
||||
! 习题11-10 复数的振幅和相位
|
||||
subroutine Exercises11_10
|
||||
implicit none
|
||||
integer, parameter :: sgl=selected_real_kind(p=2) ! 定义单精度
|
||||
complex(sgl) :: var1 ! 定义复数
|
||||
real(sgl) :: amp, theta ! 定义振幅和相位
|
||||
real(sgl), parameter :: PI=3.14159265 ! 圆周率
|
||||
call InputComplex(amp, theta) ! 调用子程序, 获取输入复数的振幅和相位
|
||||
write(*, *) '振幅为:', amp, ', 相位为:', theta, '°' ! 输出结果
|
||||
contains
|
||||
subroutine InputComplex(amp, theta)
|
||||
integer, parameter :: sgl=selected_real_kind(p=2) ! 定义单精度
|
||||
real(sgl), intent(out) :: amp, theta ! 定义输出结果
|
||||
complex(sgl) :: var1 ! 定义输入复数
|
||||
write(*, *) '请输入一个复数:' ! 提示信息
|
||||
read(*, *) var1 ! 读取输入复数
|
||||
amp = cabs(var1) ! 获取振幅
|
||||
theta = atan(aimag(var1)/real(var1))*360./(2.*PI) ! 获取相位(角度)
|
||||
end subroutine InputComplex
|
||||
end subroutine Exercises11_10
|
||||
! 习题11-11 欧拉公式
|
||||
subroutine Exercises11_11
|
||||
implicit none
|
||||
integer, parameter :: sgl=selected_real_kind(p=2) ! 定义单精度
|
||||
real(sgl) :: theta ! 定义角度(弧度)
|
||||
complex(sgl) :: var1 ! 定义复数
|
||||
real(sgl) :: PI=3.14159265 ! 圆周率
|
||||
integer :: i ! 循环参数
|
||||
do i = 0, 2 ! 循环theta = 0, pi/2, pi
|
||||
theta = i*PI/2. ! 计算theta
|
||||
write(*, '("theta = ", F6.2,", e^theta_i = " 2("(", ES9.2, ",", ES9.2, ") "))') &
|
||||
&theta, cexp(cmplx(0., theta, sgl)), EulerFormula(theta)! 输出结果
|
||||
end do
|
||||
contains
|
||||
! 欧拉公式
|
||||
function EulerFormula(theta)
|
||||
integer, parameter :: sgl=selected_real_kind(p=2) ! 定义单精度
|
||||
real(sgl), intent(in) :: theta ! 定义输入角度(弧度)
|
||||
complex(sgl) :: EulerFormula ! 定义函数返回类型
|
||||
EulerFormula = cmplx(cos(theta), sin(theta), sgl) ! 计算返回值
|
||||
end function EulerFormula
|
||||
end subroutine Exercises11_11
|
Reference in New Issue
Block a user