! ============================================================================== ! 通过 gfortran ./test.f90 -o ./run && ./run 运行 ! 程序名: ! 习题 ! 目的: ! ! 修订记录: ! 日期 编程者 改动描述 ! =================== ============= ===================================== ! 2021-04-16 19:59:35 Sola 7.3 1~4 编写源代码 ! 2021-04-16 20:30:45 Sola 修改7.3 4的代码(直接比较赋值不就好了) ! 2021-04-16 21:28:46 Sola 测试下external语句的使用 ! 2021-04-17 16:10:12 Sola 习题7-9b ! 2021-04-17 16:22:35 Sola 习题7-10 ! 2021-04-17 16:51:53 Sola 习题7-14 随机数程序 ! 2021-04-17 16:57:46 Sola 习题7-15 掷色子程序 ! 2021-04-17 17:39:09 Sola 习题7-16 泊松分布 ! 2021-04-17 18:01:03 Sola 习题7-18 计算双曲正弦值、余弦值、正切值 ! 2021-04-17 18:49:40 Sola 习题7-19 向量叉积(3维向量) ! 2021-04-17 20:16:43 Sola 习题7-20 数组排序 ! 2021-04-17 21:11:06 Sola 习题7-21 函数的最大值和最小值 ! 2021-04-17 21:45:25 Sola 习题7-22 代入函数计算 ! 2021-04-17 21:54:08 Sola 习题7-23 微分函数 ! 2021-04-18 00:54:09 Sola 习题7-24 噪声值微分 ! 2021-04-18 11:50:23 Sola 习题7-25 二进制运算(加减及进制转换) ! 2021-04-25 15:23:51 Sola 习题7-26 线性最小二乘拟合 ! 2021-04-25 16:00:28 Sola 习题7-27 最小二乘拟合的相关系数 ! 2021-04-25 16:07:05 Sola 习题7-28 生日问题 ! 2021-04-25 17:42:55 Sola 习题7-29 经时计算 ! 2021-04-25 21:04:53 Sola 习题7-30 使用计时器子程序 ! 2021-04-25 21:49:32 Sola 习题7-31 估算无限序列 ! 2021-04-25 22:45:24 Sola 习题7-32 使用子程序计算随机分布 ! 2021-04-26 00:20:22 Sola 习题7-33 高斯(正态)分布 ! 2021-04-26 01:43:23 Sola 习题7-34 引力 ! 2021-04-26 01:54:59 Sola 习题7-35 堆排序, 了解有这么个玩意就成 ! 程序结构: ! ! ============================================================================== ! 模块: module MouName implicit none ! 数据字典 ! 声明常数 REAL, PARAMETER :: PI=3.14159265 ! PI值 REAL, PARAMETER :: e=2.718281828459 ! 自然对数 INTEGER, PARAMETER :: arrayLength=20 ! 数组基准长度 REAL, PARAMETER :: criticalZero=1.0E-30 ! 0的临界值 ! 声明变量 ! real function Function1(x) ! real function Function2(x) ! integer function Function3(n) ! logical function Function4(x,y) real :: x, y integer :: n ! 创建显式接口 contains ! 习题7.3 2 real function Function2(x) implicit none real, intent(in) :: x Function2=(exp(x)-exp(-x))/(exp(x)+exp(-x)) end function Function2 ! 习题7.3 3 计算阶乘 integer function Function3(n) implicit none ! external :: Function3 integer, intent(in) :: n integer :: i Function3 = 1 do i=2,n Function3 = Function3 * i end do end function Function3 ! 习题7.3 4 logical function Function4(x, y) implicit none real, intent(in) :: x, y ! if ( x**2+y**2 > 1.0 ) then ! Function4 = .TRUE. ! else ! Function4 = .FALSE. ! end if Function4 = x**2+y**2 > 1.0 end function Function4 ! 测试用 subroutine Subroutine1(fun, x, result, errorLevel) implicit none real :: fun ! external :: fun real, intent(in) :: x real, intent(out) :: result integer, intent(out) :: errorLevel result = fun(x) end subroutine Subroutine1 ! 习题7-9 b subroutine max_char(string, big) implicit none character(len=10), intent(in) :: string character, intent(out) :: big integer :: i big = string(1:1) do i = 2,10 if ( string(i:i) > big ) then big = string(i:i) end if end do end subroutine max_char ! 叉积运算函数 function VectorProduct_3(vectorX, vectorY) implicit none real, dimension(3) :: VectorProduct_3 real, dimension(3), intent(in) :: vectorX, vectorY VectorProduct_3 = vectorX((/2,3,1/))*vectorY((/3,1,2/))-vectorY((/2,3,1/))*vectorX((/3,1,2/)) end function VectorProduct_3 ! function VectorProduct_3(vectorX, vectorY) ! implicit none ! real, dimension(3) :: VectorProduct_3 ! real, dimension(3), intent(in) :: vectorX, vectorY ! ! write(*,*) vectorX, vectorY ! ! VectorProduct_3=[1,1,1] ! VectorProduct_3 = vectorX((/2,3,1/))*vectorY((/3,1,2/))-vectorY((/2,3,1/))*vectorX((/3,1,2/)) ! end function VectorProduct_3 ! 随机数子程序 ! subroutine random(ran, iseed) ! implicit none ! real, intent(in) :: iseed ! real, intent(out) :: ran ! real :: n ! if ( iseed = '' ) then ! iseed = 12345 ! end if ! n = abs(iseed) ! n = mod(8121*n+28411,134456) ! ran = real(n)/134456 ! end subroutine random ! 字符串二进制加法运算 function BinaryAddition(strInput1, strInput2, strLength) implicit none integer, intent(in) :: strLength character(len=strLength), intent(in) :: strInput1, strInput2 character(len=strLength) :: BinaryAddition integer :: i, j j = 0 do i = 1, strLength if ( (strInput1(i:i) /= '0' .and. strInput1(i:i) /= '1') & &.or. (strInput2(i:i) /= '0' .and. strInput2(i:i) /= '1') ) stop "输入数据包含非法字符" end do do i = strLength, 1, -1 select case ( iachar(strInput1(i:i)) + iachar(strInput2(i:i)) + j ) case ( 96:96 ) BinaryAddition(i:i) = '0' ! 0+0 j = 0 case ( 97:97 ) BinaryAddition(i:i) = '1' ! 0+1, 1+0, 0+0+1 j = 0 case ( 98:98 ) BinaryAddition(i:i) = '0' ! 1+1, 1+0+1, 0+1+1 j = 1 case ( 99:99 ) BinaryAddition(i:i) = '1' ! 1+1+1 j = 1 end select end do end function BinaryAddition ! 字符串二进制减法运算 function BinarySubtraction(strInput1, strInput2, strLength) implicit none integer, intent(in) :: strLength character(len=strLength), intent(in) :: strInput1, strInput2 character(len=strLength) :: BinarySubtraction integer :: i, j j = 0 do i = 1, strLength if ( (strInput1(i:i) /= '0' .and. strInput1(i:i) /= '1') & &.or. (strInput2(i:i) /= '0' .and. strInput2(i:i) /= '1') ) stop "输入数据包含非法字符" end do do i = strLength, 1, -1 select case ( iachar(strInput1(i:i)) - iachar(strInput2(i:i)) + j ) case ( 0:0 ) BinarySubtraction(i:i) = '0' ! 0-0, 1-1, 1-0-1 j = 0 case ( 1:1 ) BinarySubtraction(i:i) = '1' ! 1-0 j = 0 case ( -1:-1 ) BinarySubtraction(i:i) = '1' ! 0-1, 0-0-1, 1-1-1 j = -1 case ( -2:-2 ) BinarySubtraction(i:i) = '0' ! 0-1-1 j = -1 end select end do end function BinarySubtraction ! 字符串二进制转整型十进制 integer function BaseConversion_2To10(Base2Str, strLength) implicit none integer, intent(in) :: strLength character(len=strLength), intent(in) :: Base2Str integer :: i, value BaseConversion_2To10 = 0 do i = 2, strLength read(Base2Str(i:i),*) value BaseConversion_2To10 = BaseConversion_2To10 + value*2**(strLength-i) end do if ( Base2Str(1:1) == '1' ) BaseConversion_2To10 = BaseConversion_2To10 - 2**(strLength-1) end function BaseConversion_2To10 ! 整数型十进制转字符串二进制 function BaseConversion_10To2(Base10Int, strLength) implicit none integer, intent(in) :: Base10Int, strLength character(len=strLength) :: BaseConversion_10To2, oneBase2 integer :: i, value value = abs(Base10Int) if ( value > 2**(strLength-1) ) stop "数值越界" do i = strLength, 1, -1 if ( mod(value, 2) == 1 ) then BaseConversion_10To2(i:i) = '1' else BaseConversion_10To2(i:i) = '0' end if value = value / 2 end do if ( Base10Int < 0 ) then do i = 1, strLength if ( BaseConversion_10To2(i:i) == '1' ) then BaseConversion_10To2(i:i) = '0' else BaseConversion_10To2(i:i) = '1' end if end do do i = 1, strLength-1 oneBase2(i:i) = '0' end do oneBase2(strLength:strLength) = '1' BaseConversion_10To2 = BinaryAddition(BaseConversion_10To2, oneBase2, strLength) end if end function BaseConversion_10To2 end module MouName ! ============================================================================== ! 主程序: program ProName use MouName implicit none ! 数据字典 ! 声明常量 ! 声明变量 ! real, external :: Function1 real :: Function1 real :: result integer :: errorLevel ! 变量初始化 ! write(*,*) '1. 输入x=2,则f(x)= ', Function1(2.) ! write(*,*) '2. 输入x=3,则tanh(x)= ', Function2(3.) ! write(*,*) '3. 11的阶乘为 ', Function3(11) ! write(*,*) '4. 输入x=3,y=4,则其平方和是否大于1.0?结果为:', Function4(3., 4.) ! call Subroutine1(Function1, 3., result, errorLevel) ! write(*,*) result ! call Exercises7_9 ! call Exercises7_10 ! call Exercises7_15 ! call Exercises7_16 ! call Exercises7_18 ! call Exercises7_19 ! call Exercises7_20 ! call Exercises7_21 ! call Exercises7_23 ! call Exercises7_25 ! call Exercises7_26 ! call Exercises7_28 ! call Exercises7_29 ! call Exercises7_31 ! call Exercises7_32 ! call Exercises7_33 ! call Exercises7_34 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 ! ============================================================================== real function Function1(x) implicit none ! 数据字典 real, intent(in) :: x Function1 = (x-1)/(x+1) end function Function1 ! 习题7-9 b 最终结果会出现警告,但可以运行,结果也是正确的,不知道是不是巧合 subroutine Exercises7_9 use MouName implicit none character(len=10) :: str = '1AbHz05Z' character :: largest call max_char (str, largest) write(*,100) str, largest 100 format(' The largest character in ', A, ' is ', A) end subroutine Exercises7_9 ! 习题7-10 module my_constants implicit none real, parameter :: PI_1 = 3.141593 real, parameter :: G_1 = 9.81 end module my_constants subroutine Exercises7_10 ! implicit none use my_constants write(*,*) 'SIN(2*PI) = ', sin(2.*PI_1) ! G_1 = 17. end subroutine Exercises7_10 ! 习题7-14 module ran001 implicit none integer :: n = 12345 end module ran001 subroutine seed0(iseed) use ran001 implicit none real, intent(in) :: iseed n = abs(iseed) end subroutine seed0 subroutine random(ran) use ran001 implicit none real, intent(inout) :: ran n = mod(8121*n+28411,134456) ran = real(n)/134456 end subroutine random subroutine Exercises7_14 implicit none real :: randomSeed = 123456 real :: randomValue integer :: i call seed0(randomSeed) do i = 1,10 call random(randomValue) randomValue = randomValue*2.-1 write(*,*) randomValue end do end subroutine Exercises7_14 ! 习题7-15 subroutine Exercises7_15 implicit none real :: randomSeed = 123456 real :: randomValue, sum = 0 integer :: i, point integer, dimension(6) :: pointSum call seed0(randomSeed) pointSum = 0 do i = 1,1000000 call random(randomValue) point = int(randomValue*6+1) ! write(*,*) '你掷到了数字', point pointSum(point) = pointSum(point) + 1 end do write(*,*) '各点数计数分别为:', (pointSum(i), ',', i = 1, 6) end subroutine ! 习题7-16 subroutine Exercises7_16 implicit none real :: countPerMinute, time, probability, PoissonDistribution integer :: k countPerMinute=1.6 time=1. do k = 0, 5 probability = PoissonDistribution(k, time, countPerMinute) write(*,*) '一分钟内有', k, '辆车经过的可能性为', probability end do end subroutine Exercises7_16 ! 泊松分布函数 real function PoissonDistribution(k, t, countBar) implicit none integer, intent(in) :: k real, intent(in) :: t, countBar integer :: i, kFactorial kFactorial = 1 do i = 2, k kFactorial = kFactorial*i end do PoissonDistribution = exp(-countBar*t)*(countBar*t)**k/real(kFactorial) end function PoissonDistribution ! 习题7-18 subroutine Exercises7_18 implicit none real :: x, FunSinh, FunCosh, FunTanh integer :: i real, dimension(11) :: numList=[-2.0,-1.5,-1.0,-0.5,-0.25,0.0,0.25,0.5,1.0,1.5,2.0] x = 1.2 write(*,*) '双曲正弦值:计算结果为:', FunSinh(x), '验证值为:', sinh(x) write(*,*) '双曲余弦值:计算结果为:', FunCosh(x), '验证值为:', cosh(x) write(*,*) '双曲正切值:计算结果为:', FunTanh(x), '验证值为:', tanh(x) write(*,*) write(*,1) 'Num ', numList write(*,*) '==== ======== ======== ======== ======== ======== & &======== ======== ======== ======== ======== ========' write(*,1) 'Sinh', (FunSinh(numList(i)), i = 1, 11) write(*,1) 'CosH', (FunCosh(numList(i)), i = 1, 11) write(*,1) 'Tanh', (FunTanh(numList(i)), i = 1, 11) 1 format(1X, A4, 11(1X, F8.5)) end subroutine Exercises7_18 ! 双曲正弦 real function FunSinh(x) implicit none real, intent(in) :: x FunSinh = (exp(x)-exp(-x))/2 end function FunSinh ! 双曲余弦 real function FunCosh(x) implicit none real, intent(in) :: x FunCosh = (exp(x)+exp(-x))/2 end function FunCosh ! 双曲正切 real function FunTanh(x) implicit none real, intent(in) :: x FunTanh = (exp(x)-exp(-x))/(exp(x)+exp(-x)) end function FunTanh ! 习题7-19 向量叉积(三维向量) subroutine Exercises7_19 use MouName implicit none real, dimension(3) :: array1 ! 矢量1 real, dimension(3) :: array2 ! 矢量2 real, dimension(3) :: arrayResult ! 结果矢量 array1 = [-2.,4.,0.5] array2 = [0.5,3.,2.] write(*,1) VectorProduct_3(array1, array2) 1 format(1X, "矢量V1与矢量V2的差积为:", 3(1X, F6.2)) end subroutine Exercises7_19 ! 叉积运算子程序,为啥子程序能运行,函数不可以,一定要放到模组里,,,是真的恶心,不然就会被当作调用数组而不是调用函数 ! subroutine VectorProduct_3(vectorX, vectorY, arrayResult, n) ! implicit none ! integer :: n ! real, intent(in), dimension(n) :: vectorX, vectorY ! real, intent(out), dimension(n) :: arrayResult ! arrayResult = vectorX((/2,3,1/))*vectorY((/3,1,2/))-vectorY((/2,3,1/))*vectorX((/3,1,2/)) ! end subroutine VectorProduct_3 ! 习题7-20 数组排序 subroutine Exercises7_20 implicit none integer, parameter :: arrayLength = 9 real, dimension(arrayLength) :: arr1, arr2 arr1 = (/1.,11.,-6.,17.,-23.,0.,5.,1.,-1./) arr2 = (/31.,101.,36.,-17.,0.,10.,-8.,-1.,-1./) call ArraySort(arr1, arr2, arrayLength) write(*,1) 'arr1:', arr1 write(*,1) 'arr2:', arr2 1 format(1X, A, 9(F7.2, 1X)) end subroutine Exercises7_20 ! 习题7-20 数组排序 subroutine ArraySort(arrayBase, arrayEntourage, n) implicit none integer :: n real, intent(inout), dimension(n) :: arrayBase, arrayEntourage integer :: i, j, maxPosition real :: maxValue do i = 1, n - 1 maxPosition = i do j = i + 1, n if ( arrayBase(maxPosition) < arrayBase(j) ) then maxPosition = j end if end do if ( i /= maxPosition ) then maxValue = arrayBase(maxPosition) arrayBase(maxPosition) = arrayBase(i) arrayBase(i) = maxValue maxValue = arrayEntourage(maxPosition) arrayEntourage(maxPosition) = arrayEntourage(i) arrayEntourage(i) = maxValue end if end do end subroutine ArraySort ! 习题7-21 函数的最大值和最小值测试驱动程序 subroutine Exercises7_21 implicit none real :: xStart, xEnd, xInc, minPosition, maxPosition, minValue, maxValue real, external :: Exercises7_21_fun call SearchFunctionExtermeValue(-1., 3., 200, Exercises7_21_fun, minPosition, minValue, maxPosition, maxValue) write(*,1) 'Exercises7_21_fun 在 x = ', maxPosition, ' 处取到最大值 ',& & maxValue, ',在 x = ', minPosition, ' 处取到最小值 ', minValue 1 format(1X, A, F5.2, A, F5.2, A, F5.2, A, F5.2) end subroutine Exercises7_21 ! 习题7-21 求取函数的最大值和最小值 subroutine SearchFunctionExtermeValue(firstValue, lastValue, numSteps, func, xmin, minValue, xmax, maxValue) implicit none real, intent(in) :: firstValue, lastValue real, intent(out) :: xmin, xmax, minValue, maxValue integer, intent(in) :: numSteps real :: xInc real, external :: func real :: value, temp value = firstValue xmin = value xmax = value temp = func(value) minValue = temp maxValue = temp do value = value + (lastValue-firstValue)/numSteps if ( value > lastValue ) exit temp = func(value) if ( temp > maxValue ) then xmax = value else if ( temp < minValue ) then xmin = value end if end do maxValue = func(xmax) minValue = func(xmin) end subroutine SearchFunctionExtermeValue ! 习题7-22 自定义函数给7-21 real function Exercises7_21_fun(x) implicit none real :: x Exercises7_21_fun = x**3-5*x**2+5*x+2 end function Exercises7_21_fun ! 习题7-23 微分函数测试驱动程序 + 习题7-24 噪声值微分 ! 程序结构: ! x = 0 ! dx = 0.05 ! 输入向量 = (sin(0+i*dx), i = 0,99) ! 调用子程序, 输入: 输入向量(100) 个数 dx 输出向量(99) ! 验证向量 = (cos(0+i*dx), i = 0,98) ! write 计算结果于实际值的接近程度判断结果为: abs(输出向量-验证向量) <= 临界值 ! 子程序(输入向量(向量长度), 向量长度, 步长, 输出向量(向量长度-1)) ! if abs(步长) <= 临界值 then ! write error! ! exit ! else ! 输出向量(i) = ((输入向量(i+1)-输入向量(i))/步长, i = 1, 99) ! end if subroutine Exercises7_23 use MouName implicit none integer, parameter :: numSteps = 100 real, dimension(numSteps) :: arrayInput real, dimension(numSteps-1) :: arrayResult, arrayCheck real, dimension(numSteps-1) :: arrayNoise integer :: i real :: stepsLength stepsLength = 0.05 arrayInput = [(sin(0+i*stepsLength), i = 0, numSteps-1)] call Differential(arrayInput, numSteps, stepsLength, arrayResult) arrayCheck = [(cos(0+i*stepsLength), i = 0, numSteps-2)] write(*,*) '计算结果符合程度判断:', all((abs(arrayCheck-arrayResult) <= 0.05) .eqv. .TRUE.) call RandomArrayCreator(numSteps-1, arrayNoise) ! arrayResult = arrayResult + arrayNoise * 0.04 - 0.02 write(*,'(10F6.2)') arrayResult - arrayCheck end subroutine Exercises7_23 ! 习题7-23 微分计算子程序 subroutine Differential(arrayInput, numSteps, stepsLength, arrayOutput) use MouName integer, intent(in) :: numSteps real, dimension(numSteps), intent(in) :: arrayInput real, dimension(numSteps-1), intent(out) :: arrayOutput real, intent(in) :: stepsLength if ( abs(stepsLength) <= criticalZero ) then stop '步长过小, 请检查后再编译执行' else arrayOutput = [((arrayInput(i+1)-arrayInput(i))/stepsLength, i = 1, numSteps-1)] end if end subroutine Differential ! 噪声值产生(产生指定数目0~1的随机数) subroutine RandomArrayCreator(randomNum, arrayOutput) implicit none real :: randomSeed = 207333 integer, intent(in) :: randomNum real, dimension(randomNum), intent(out) :: arrayOutput integer :: i call seed0(randomSeed) ! arrayOutput = (/(call random(randomValue), i = 1, randomNum)/) ! call不返回值! do i = 1, randomNum call random(arrayOutput(i)) end do end subroutine RandomArrayCreator ! 习题7-25 二进制补运算测试驱动程序 subroutine Exercises7_25 use MouName implicit none integer, parameter :: strLength = 8 character(len=strLength) :: str1, str2, strResult integer :: intAdd, intSub str1 = '11111111' str2 = '00000001' ! strResult = BinaryAddition(str1, str2, strLength) intAdd = BaseConversion_2To10(BinaryAddition(str1, str2, strLength), strLength) intSub = BaseConversion_2To10(BinarySubtraction(str1, str2, strLength), strLength) write(*,*) str1, ' + ', str2, ' 的结果为 ', BaseConversion_10To2(intAdd, strLength) write(*,*) str1, ' - ', str2, ' 的结果为 ', BaseConversion_10To2(intSub, strLength) write(*,*) BaseConversion_2To10(str1, strLength), ' + ', BaseConversion_2To10(str2, strLength), ' 的结果为 ', intAdd write(*,*) BaseConversion_2To10(str1, strLength), ' - ', BaseConversion_2To10(str2, strLength), ' 的结果为 ', intSub end subroutine Exercises7_25 ! 习题7-26 线性最小二乘拟合 习题7-27 最小二乘拟合的相关系数 测试驱动程序 subroutine Exercises7_26 implicit none integer, parameter :: arrayLength=20 real, dimension(arrayLength) :: arrayX, arrayY real :: m, b, r arrayX = (/-4.91, -3.84, -2.41, -2.62, -3.78, -0.52, -1.83, -2.01, +0.28, +1.08& &, -0.94, +0.59, +0.69, +3.04, +1.01, +3.60, +4.53, +5.12, +4.43, +4.12/) arrayY = (/-8.18, -7.49, -7.11, -6.15, -5.62, -3.30, -2.05, -2.83, -1.16, +0.52& &, +0.21, +1.73, +3.96, +4.26, +5.75, +6.67, +7.70, +7.31, +9.05, 10.95/) call LeastSquaresMethod(arrayX, arrayY, arrayLength, m, b, r) write(*,1) m, b, r 1 format(1X, '计算得到的拟合方程为: y = ', F5.2, ' * x + ', F5.2, ' , 相关系数r为: ', F5.3) end subroutine Exercises7_26 ! 习题7-26 最小二乘法计算各参数(斜率、截距、相关系数) subroutine LeastSquaresMethod(arrayX, arrayY, arrayLength, slope, intercept, correlationCoefficient) implicit none integer, intent(in) :: arrayLength ! 设定数组长度 real, dimension(arrayLength),intent(in) :: arrayX, arrayY ! 设定输入X、Y坐标数组 real, intent(out) :: slope, intercept, correlationCoefficient ! 设定输出斜率、截距和相关系数 integer :: i ! 循环变量 real :: x_bar, y_bar ! xy均值 real :: r ! 相关系数 real :: x_sum, y_sum ! xy总和 real :: x2_sum, xy_sum, y2_sum ! 各种参数 ! 变量初始化 x_sum = 0 y_sum = 0 x2_sum = 0 y2_sum = 0 xy_sum = 0 i = 0 do i = 1, arrayLength ! 循环计算各参数 x_sum = x_sum + arrayX(i) ! x总和 y_sum = y_sum + arrayY(i) ! y总和 x2_sum = x2_sum + arrayX(i)**2 ! x方总和 y2_sum = y2_sum + arrayY(i)**2 ! y方总和 xy_sum = xy_sum + arrayX(i)*arrayY(i) ! xy总和 end do x_bar = x_sum/real(i) ! x均值 y_bar = y_sum/real(i) ! y均值 slope = ( xy_sum - x_sum*y_bar )/( x2_sum - x_sum*x_bar ) ! 斜率 intercept = y_bar - slope*x_bar ! 截距 correlationCoefficient = ( real(i)*xy_sum - x_sum*y_sum )/& ! 相关系数 &sqrt( (real(i)*x2_sum - x_sum**2 )*( real(i)*y2_sum - y_sum**2 ) ) end subroutine LeastSquaresMethod ! 习题7-28 生日问题 subroutine Exercises7_28 implicit none integer :: numPerson ! 房间内人数 real :: CompletelyDifferentProbability ! 调用理论值计算函数 real :: DifferentProbabilityTest ! 测试概率值计算 do numPerson = 2, 40 write(*,*) numPerson, '个人生日不同的理论概率为', CompletelyDifferentProbability(numPerson, 365) write(*,*) numPerson, '个人生日不同的测试概率为', DifferentProbabilityTest(numPerson, 365) end do end subroutine Exercises7_28 ! n个特定范围内的整数, 彼此之间完全不同的概率 real function CompletelyDifferentProbability(num, total) implicit none integer, intent(in) :: num ! 样本个数 integer, intent(in) :: total ! 可能的样本值总数 integer :: i ! 循环参数 CompletelyDifferentProbability = 1. ! 初始化输出 do i = 1, num - 1 CompletelyDifferentProbability = CompletelyDifferentProbability * real(total - i) / real(total) end do end function CompletelyDifferentProbability ! 从随机数中求n个特定范围内的整数, 彼此之间完全不同的概率 real function DifferentProbabilityTest(num, total) implicit none integer, intent(in) :: num ! 样本个数 integer, intent(in) :: total ! 样本值可能情况总数 integer, dimension(num) :: arrayTemp ! 样本值临时数组 integer, parameter :: numTest=90000 ! 测试次数 real :: randomValue integer :: i, j ! 循环参数 integer :: temp ! 用于保存生成的随机数的临时值 call seed0(111111.) ! 获取初始随机参数 DifferentProbabilityTest = real(numTest) ! 初始化输出为测试次数 do i = 1, numTest ! 测试循环开始 arrayTemp = -1 ! 初始化随机数组 check: do j = 1, num ! 检查是否存在相同值循环 call random(randomValue) ! 获取一个1~0随机数 temp = floor(randomValue*total) ! 将随机数转化为1~总数之间的整数值 if ( any(arrayTemp==temp) ) then ! 如果存在相同数字 DifferentProbabilityTest = DifferentProbabilityTest - 1.! 中间值-- exit check ! 退出给随机数组赋值 end if ! 如果结束 arrayTemp(j) = temp ! 给随机数组当前位赋值 end do check ! 该次测试结束 end do ! 所有测试结束 DifferentProbabilityTest = DifferentProbabilityTest/real(numTest) ! 生成输出值(概率) end function DifferentProbabilityTest ! 习题7-29 经时计算 习题公共模块 module ModuleExercises7_29 ! 定义模块 implicit none ! 声明显示表达 ! 数据字典 integer, dimension(8) :: timeNow ! 当前时间数组 integer, dimension(8) :: timeOld ! 上一个时间数组 contains ! 所包含函数和子程序 ! 习题7-29 经时计算 子程序1 subroutine set_timer ! 创建子程序1 implicit none ! 声明显示表达 call DATE_AND_TIME(values=timeNow) ! 调用当前时间子程序 end subroutine set_timer ! 结束子程序1 ! 习题7-29 经时计算 子程序2 subroutine elapsed_time(timePast) ! 创建子程序2 implicit none ! 声明显示表达 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 end module ModuleExercises7_29 ! 结束模块 ! 习题7-29 经时计算 测试驱动程序 习题7-30 子程序计算 subroutine Exercises7_29 ! 定义测试驱动程序 use ModuleExercises7_29 ! 读取模块 implicit none ! 显式声明 integer, parameter :: arrayLength=100 ! 定义数组基础长度 real :: array1(arrayLength), array2(arrayLength*10), array3(arrayLength*100) ! 定义使用的随机数数组 real :: timePast ! 定义经历时间长度变量 real :: time1, time2, time3 ! 每次排序所消耗的时间 integer :: i, j ! 循环参数 ! 变量初始化 time1 = 0 time2 = 0 time3 = 0 ! 多次循环计算时间, 统计循环次数与用时总和 do j = 1, 10 call seed0(111111.) ! 随机数种子 do i = 1, 100 ! 给array1赋值 call random(array1(i)) end do do i = 1, 1000 ! 给array2赋值 call random(array2(i)) end do do i = 1, 10000 ! 给array3赋值 call random(array3(i)) end do call set_timer ! 计算array1排序所需时间 call Sort(array1, arrayLength) call elapsed_time(timePast) time1 = time1 + timePast ! array1排序时间总计 call set_timer ! 计算array2排序所需时间 call Sort(array2, arrayLength*10) call elapsed_time(timePast) time2 = time2 + timePast ! array2排序时间总计 call set_timer ! 计算array3排序所需时间 call Sort(array3, arrayLength*100) call elapsed_time(timePast) time3 = time3 + timePast ! array3排序时间总计 end do ! 计算排序所需时间均值 time1 = time1/real(i) time2 = time2/real(i) time3 = time3/real(i) write(*,1) time1, time2, time3 ! 打印排序时间信息 1 format(1X, '排序三个数组分别经历了', /& &1X, '1. ', F10.8, ' s', /& &1X, '2. ', F10.8, ' s', /& &1X, '3. ', F10.8, ' s') end subroutine Exercises7_29 ! 习题7-30 排序子程序 subroutine Sort(array, n) implicit none integer :: n ! 数组长度 real, intent(inout), dimension(n) :: array ! 定义输入输出数组 integer :: i, j, maxPosition ! 循环参数和最大值位置 real :: maxValue ! 最大值的值 ! 对数组进行排序 do i = 1, n - 1 maxPosition = i do j = i + 1, n if ( array(maxPosition) < array(j) ) then maxPosition = j end if end do if ( i /= maxPosition ) then maxValue = array(maxPosition) array(maxPosition) = array(i) array(i) = maxValue end if end do end subroutine Sort ! 习题7-31 估算无限序列 测试驱动程序 subroutine Exercises7_31 implicit none integer, parameter :: arrayLength=8 ! 数组长度 real, dimension(arrayLength) :: arrayX, arrayY ! 输入数组X与输出数组Y real :: ExEstimation ! 定义函数返回值类型 integer :: i ! 循环参数 arrayX = (/-10., -5., -1., 0., 1., 5., 10., 15./) ! 赋值输入数组X ! arrayY = (/((ExEstimation(arrayX(i)), i = 1, arrayLength))/) ! 好像不能这样用隐式循环 do i = 1, arrayLength ! 循环求输出数组Y的值 arrayY(i) = ExEstimation(arrayX(i)) ! 调用函数赋值 end do write(*,1) arrayX, arrayY, exp(arrayX) ! 输出结果表格 1 format(1X, 'Form. e^x value estimation'/& &1X, 'Input ', 8(1X, F9.2)/& &1X, 'Output ', 8(1X, ES9.2)/& &1X, 'Real ', 8(1X, ES9.2)) end subroutine Exercises7_31 ! 习题7-31 EXP(X) real function ExEstimation(x) implicit none real, intent(in) :: x ! 定义输入变量指数值 integer :: n ! 循环参数n integer :: nFactorial ! n的阶乘 ! 初始化变量 ExEstimation = 0 nFactorial = 1 do n = 0, 11 ! 取无限序列前12项 ExEstimation = ExEstimation + x**n/nFactorial ! 加和趋近结果值 nFactorial = nFactorial*(n+1) ! 计算下一次循环需要的阶乘值 end do end function ExEstimation ! 习题7-32 使用子程序计算随机分布情况 subroutine Exercises7_32 implicit none integer, parameter :: arrayLength=10000 ! 定义数组长为10000 real, dimension(arrayLength) :: array ! 定义随机数组 real :: Average, StandardDeviation ! 定义平均值和标准差为实型 integer :: i ! 循环参数 call seed0(111111.) ! 初始化随机数 do i = 1, arrayLength ! 循环给随机数组赋值 call random(array(i)) end do ! 输出结果 write(*,*) '随机数组平均值为: ', Average(array, arrayLength) write(*,*) '随机数组标准差为: ', StandardDeviation(array, arrayLength) write(*,*) '理论的平均值是0.5, 理论的标准偏差是', 1/sqrt(12.) end subroutine Exercises7_32 ! 习题7-33 计算数列平均值与标准偏差 real function Average(arrayInput, arrayLength) implicit none integer, intent(in) :: arrayLength ! 定义数组长度 real, dimension(arrayLength), intent(in) :: arrayInput ! 定义输入数组 integer :: i ! 循环参数 Average = 0 ! 初始化输出 do i = 1, arrayLength ! 循环加和数组值 Average = Average + arrayInput(i) end do Average = Average/real(i) ! 计算平均值 end function Average real function StandardDeviation(arrayInput, arrayLength) implicit none integer, intent(in) :: arrayLength ! 定义数组长度 real, dimension(arrayLength), intent(in) :: arrayInput ! 定义输入数组 integer :: i ! 循环参数 real :: average ! 定义平均值 average = 0 ! 初始化平均值 StandardDeviation = 0 ! 初始化标准差 do i = 1, arrayLength ! 循环加和数组值 average = average + arrayInput(i) end do average = average/i ! 计算平均值 do i = 1, arrayLength ! 循环加和平均值与数组值的平方差 StandardDeviation = StandardDeviation + (average - arrayInput(i))**2 end do StandardDeviation = sqrt(StandardDeviation/(i - 1)) ! 计算标准偏差 end function StandardDeviation ! 习题7-33 高斯(正态)分布 subroutine Exercises7_33 implicit none integer, parameter :: arrayLength=1000 ! 定义数组长度 real, dimension(arrayLength) :: arrayNormal ! 定义随机正态分布数组 integer :: i ! 循环参数 real :: StandardDeviation, Average ! 定义函数返回值类型 call seed0(111111.) ! 初始化随机数 ! do i = 1, int(arrayLength/2) ! 按照书上方法生成正态分布随机值 ! call NormallyDistributedRandomValue(arrayNormal(2*i-1), arrayNormal(2*i)) ! end do do i = 1, arrayLength ! 使用Box–Muller变换得到正态分布随机值 call NormallyDistributedRandomValue1(arrayNormal(i)) end do ! write(*,'(25(F5.2, 1X))') arrayNormal ! 显示计算得到的正态分布数据 write(*,*) '标准的正态分布标准偏差为1.0, 而计算得到的随机数列标准偏差为',& & StandardDeviation(arrayNormal, arrayLength), '平均值为',& & Average(arrayNormal, arrayLength) ! 显示数据集的标准偏差与平均值 end subroutine ! 习题7-33 高斯分布(书上方法) subroutine NormallyDistributedRandomValue(outputValue1, outputValue2) implicit none real, intent(out) :: outputValue1, outputValue2 ! 定义输出数据 real :: r ! 定义r值 do ! 循环获取x1,x2并判断 call random(outputValue1) call random(outputValue2) if ( outputValue1**2 + outputValue2**2 - 1. <= 0 ) exit ! 如果平方和小于1, 那么结束循环 end do r = outputValue1**2 + outputValue2**2 ! 计算平方和 ! write(*,*) r outputValue1 = sqrt(-2.*log(r)/r)*outputValue1 ! 计算y1(输出值1) outputValue2 = sqrt(-2.*log(r)/r)*outputValue2 ! 计算y2(输出值2) end subroutine NormallyDistributedRandomValue ! 习题7-33 高斯分布(Box–Muller变换) subroutine NormallyDistributedRandomValue1(outputValue) implicit none real, parameter :: PI = 3.14159265 ! 定义常数PI real, intent(out) :: outputValue ! 定义输出值(符合正态分布的) real :: outputValue1 ! 另一个需要的变量,但是不输出 call random(outputValue1) ! 获取均匀分布的随机数第一个数值 call random(outputValue) ! 获取均匀分布的随机数第二个数值 outputValue = sqrt(-2.*log(outputValue1))*cos(2*PI*outputValue) ! Box–Muller变换, 并输出结果 end subroutine NormallyDistributedRandomValue1 ! 习题7-34 引力 subroutine Exercises7_34 implicit none real, parameter :: mEarth=5.98E24 ! 地球质量(kg) real :: m ! 卫星质量(kg) real :: r ! 地心与卫星距离(m) real :: Gravity ! 定义函数返回类型为实型 m = 1000. ! 设定卫星质量(kg) r = 38000.*1000. ! 设定地卫距离(m) write(*,*) '地球与卫星之间的引力大小为', Gravity(m, mEarth, r), ' N' end subroutine Exercises7_34 ! 引力计算 real function Gravity(m1, m2, r) implicit none real, parameter :: G=6.672E-11 ! 万有引力常数 real, intent(in) :: m1, m2, r ! 输入实型质量1,质量2,间距 Gravity = G*m1*m2/r**2 ! 输出两物体间引力值 end function Gravity ! 习题7-35 堆排序 ! 了解有这么个玩意就成