【问题标题】:Fortran do loop not calculating the entered variableFortran do 循环不计算输入的变量
【发布时间】:2019-02-21 14:01:17
【问题描述】:

当我只运行摄氏温度的代码时,我得到的结果低于代码:

    program temperature
! F C temperature conversion
implicit none
real :: celcius=0.0, fahrenheit=0.0

integer:: t,n
print *,'enter the number of lines'
read*, n
do n=1,n
print*,'enter the  value of t: one per line',n
read*, t
celcius=5/9*(t-32)

enddo
do n=1,n
print*, t, celcius
enddo
end program

结果

    enter the number of lines
3
 enter the  value of t: one per line           1
50
 enter the  value of t: one per line           2
20
 enter the  value of t: one per line           3
10
          10   0.00000000E+00
          10   0.00000000E+00
          10   0.00000000E+00
          10   0.00000000E+00

很明显,编译器没有在计算中选择t 的值。

【问题讨论】:

  • 只有在第一个循环中输入的最后一个值提供了循环外t 的值。如果你想使用多个值,你应该使用一个数组,或者在第一个循环周围重新构造其余部分。

标签: fortran do-loops


【解决方案1】:

您有多种选择。

  1. 将输入存储在一个数组中并处理该数组。

    program temperature
      ! F C temperature conversion
      implicit none
    
      real, allocatable :: fahrenheit(:)
      integer:: n
    
      print *,'enter the number of lines'
      read*, n
      allocate(fahrenheit(n))
      print*,'enter the  value of t: all items on one line'
      read*, fahrenheit
      print *, 'F: ', fahrenheit
      print *, 'C:', fahrenheit_to_celcius(fahrenheit)
    
    contains
    
      pure elemental function fahrenheit_to_celcius(t_f) result(t_c)
        real, intent(in) :: t_f
        real :: t_c
    
        t_c = 5.*(t_f-32.)/9.
    
      end function fahrenheit_to_celcius
    
    end program
    
  2. 一次处理一个输入

    program temperature
      ! F C temperature conversion
      implicit none
    
      real :: fahrenheit
      integer:: i, n
    
      print *,'enter the number of lines'
      read*, n
    
      do i = 1, n
         print*,'enter the  value of t: one per line',n
         read*, fahrenheit
         print *, 'F: ', fahrenheit, 'C:', fahrenheit_to_celcius(fahrenheit)
      enddo
    
    contains
    
      pure elemental function fahrenheit_to_celcius(t_f) result(t_c)
        real, intent(in) :: t_f
        real :: t_c
    
        t_c = 5.*(t_f-32.)/9.
    
      end function fahrenheit_to_celcius
    
    end program
    

请注意,我已经为函数使用了 elemental 关键字。这意味着您可以传递标量和数组。对于直接计算,这是一个很好的解决方案,例如这里的一个:例程 fahrenheit_to_celcius 在两种情况下都是相同的。

我修复了5/9(返回 0)和混合变量。

【讨论】:

  • 嗨,感谢您的帮助....我已经按照您在第二种方法中的建议得到了结果,但无法以表格形式输出,我认为数组可以到目前为止,因为我还没有到你的代码中的最后一个块的功能
  • 通过“表格形式”,您是指随后的行,首先是 C 中的温度,然后是 F 中的温度?如果是这样,只需循环第一个示例中的输出数组,如下所示:do i = 1, nprint *, fahrenheit(i), fahrenheit_to_celcius(fahrenheit(i))end do。将这些放在后面的行中,不要忘记将变量 i 声明为 integer :: i
【解决方案2】:

你至少有三个问题:

  1. 表达式5/9*(t-32) 是从左到右计算的,所以5/9 部分是一个整数(截断)除法,总是产生0。零与任何东西的乘积有限是零。有几种方法可以解决这个问题,但更简单的方法之一是将表达式重写为 5 * (t - 32) / 9

  2. 您的变量 tcelcius 是标量。他们每次只持有一个号码。在您的第一个循环中,您按顺序为它们中的每一个分配多个值。当您稍后执行第二个循环以打印结果时,只能访问分配给每个变量的最后一个值。如果您必须将输出推迟到读取所有输入之后,那么处理它的一种方法是使tcelcius 数组具有足够的大小,并将您的值存储在不同的元素中。 (另请注意:英文单词的正确拼写是“celsius”。)

  3. 根据 cmets 中的 @albert,在索引的 do 循环完成后,迭代变量的值是它在循环的下一次迭代中应该拥有的值,如果有的话。因此,通过使用变量n 作为迭代变量和上限,您会导致其值在每次循环之后都与之前不同。有几种方法可以解决这个问题,但我敦促您避免重复使用 n 作为迭代变量。避免使用有目的的迭代变量不会提高效率。

【讨论】:

  • 所以如果不在这里使用数组我将无法以表格形式查看结果?很抱歉,我知道这是一个愚蠢的问题,但我正在尝试了解数组和循环的工作原理
  • 我觉得还有个更严重的问题:do n=1,n,即重新定义n的值
  • 这是一个有趣的观察,@albert,主要是因为它出人意料地错误。在符合标准的 Fortran 实现中,索引do 循环的迭代次数在进入循环之前计算(好像)。因此,如果上限由变量给出,并且该变量在循环执行期间被修改,包括如果它用作迭代变量,则迭代次数不受影响。实际上,您可以在 OP 报告的输出中看到它的效果。
  • 您尤其可以看到,在第一个循环中,初始 n 的值为 3,而在第二个循环中,初始 n 的值为 4(不是 100% 肯定,但我认为实际上循环结束时循环计数器的值取决于实现)。
  • 是的,@albert,我只是在写一个关于这个的附录。我不同意它构成一个“更严重”的问题,但它确实需要解决,我将很快更新这个答案来讨论这个问题。但是循环后迭代变量的值没有不确定性;例如,请参阅stackoverflow.com/a/43211598/2402272
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-18
  • 1970-01-01
  • 2013-08-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多