为什么我必须在 Fortran 中隐式指定函数的双精度返回值?

2024-03-31

我是 Fortran 新手,我正在尝试common堵塞。我的代码很简单

program main
    implicit double precision (p)
    real * 8 :: x, y
    common /yvalue/ y
    x = 3d0
    y = 3d0
    print *, power(x)
end program main

function power(x)
    implicit none
    real * 8 :: power
    real * 8 :: x, y
    common /yvalue/ y
    power = x ** y
end function power

它有效,但如果我注释掉第二行,它隐式声明以p为了双精度,编译器会抱怨以下内容

Error: Return type mismatch of function ‘power’ at (1) (REAL(4)/REAL(8))

我确实明白返回值power默认情况下是一个单精度变量,但为什么要声明power因为函数中的双精度还不够吗?以及为什么写作real * 8 power in main也行不通?


当您尝试在代码中调用的过程(函数或子例程)位于outside你的身体program并且也不属于任何module,它被命名为外部函数(或子程序)。

Fortran 是一种静态类型语言,因此必须在编译时知道所有变量和函数的类型。因此,如果您想在程序中引用外部函数,则必须有一种方法让程序知道其返回类型。你有 3 (bad)选项,我将从最差的开始列出它们:


  1. WORST:依赖隐式类型规则,该规则恰好将外部函数的返回类型与调用者中与其标识符关联的类型相匹配(正如您在示例中所做的那样)。

为什么你不应该这样做? 因为它是癌症。这使得代码的含义变得模糊,你无法知道这个名字指的是什么。在某些情况下,它甚至可能看起来像一个数组变量,而不是一个函数。此外,在这种情况下,编译器不会检查参数一致性,因此如果您没有打开特定的编译器选项,代码将在以下位置失败:runtime,或更糟糕的是,会给出错误的结果。此外,隐式类型现在很少有用,大多数时候这是自找麻烦。总是使用implicit none!

正如您所指出的,根据隐式类型的默认规则,任何名称以p将被默认real类型(在你的编译器中,它是real(4))。正如您将函数结果声明为real*8,你的编译器解释为real(8)(见最后的注释),错误就出现了。


  1. BAD:在调用者指定区域声明函数的名称和类型。

就像声明变量一样,如下所示:

program main
implicit none
real*8 :: x, y, power

顺便说一句,属性external可以应用于像您这样的外部程序。不仅仅是为过程提供一些属性(可以作为实际参数传递,消除内部过程的歧义),它还可以使标识符的起源更加清晰。

program main
implicit none
real*8 :: x, y, power
external :: power

为什么你不应该这样做?编译器也没有进行参数检查。这严重限制了与外部函数通信的选项:参数不能被假定形状、假定等级、多态、参数化、coarray 或在被调用方声明为allocatable, optional, pointer, target, asynchronous, volatile or value;返回类型不能是数组、指针或可分配类型;该函数不能作为参数传递,是elemental而如果pure,不能在这种情况下使用。而这一切的原因就是缺乏一个显式接口.


  1. 可接受:指定一个interface对于调用者中的外部函数。

像这样:

program main
implicit none
interface
  real*8 function power(y)
    real*8 :: y
  end function
end interface

这样,编译器就能够知道声明的所有细节,并且我提到的所有限制都将不适用。完全自由和代码清晰!

为什么你不应该这样做?因为有更好的方法,那就是使用modules!好吧,如果你不能使用模块,那么在上下文中执行此操作是完全可以的,例如当使用已经存在的大型旧代码时。缺点是,您在两个不同的地方有几乎相同的代码,并且它们必须始终匹配。


Bonus: BETTER:使用模块。

program main
  use :: aux_module
  implicit none
  real*8 :: x, y
  common /yvalue/ y
  x = 3d0
  y = 3d0
  print *, power(x)
end

module aux_module
  implicit none
contains
  function power(x)
    real*8 :: power
    real*8 :: x, y
    common /yvalue/ y
    power = x ** y
  end
end

为什么你绝对应该这样做?因为使用模块,接口会自动且隐式地可用(代码重复更少,没有限制);模块可以单独重新编译和更新,而不会破坏代码。此外,您可以在模块范围内声明共享变量并避免使用common声明。您的代码的更好版本是:

program main
  use aux_module
  implicit none
  real*8 :: x
  x = 3d0
  y = 3d0
  print *, power(x)
end

module aux_module
  implicit none
    real*8 :: y
contains
  function power(x)
    real*8 :: power
    real*8 :: x
    power = x ** y
  end
end

甚至可以选择将您的功能直接包含到您的program, after contains。仅当您不打算在其他程序单元中重用此函数时才建议这样做。 @伊恩布什的answer https://stackoverflow.com/a/53425499/2938526涵盖了这个案例。

最后注意:看一下这个答案 https://stackoverflow.com/questions/3170239/fortran-integer4-vs-integer4-vs-integerkind-4看看为什么语法real*8是非标准的,应该避免。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么我必须在 Fortran 中隐式指定函数的双精度返回值? 的相关文章

随机推荐

  • 打开htaccess密码保护页面没有提示

    我在网站上有一个目录 该目录通过 htaccess 进行密码保护 我希望能够通过我的应用程序打开此网页 而无需用户输入密码 而是以编程方式打开此网页 例如 有没有办法可以将登录信息嵌入到 URL 中 例如http www mypage co
  • 如何在textarea中使用keydown事件?

    我不太习惯使用 javascript 但我已经厌倦了在工作中手动重复尝试 当我在论坛中写作时 我需要一个快速的简短命令 例如 Ctrl Alt z 来将一些文本插入到文本区域对象中 我已经编写了一个在文本光标 insertAtCursor
  • 在 XCode 中向表视图 (UITableView) 添加单元格

    我是 X Code 新手 刚刚开始开发我的第一个应用程序 我正在使用故事板 在导航控制器场景中 我添加了一个带有两个单元的 MasterViewController 这导致了两个 DetailViewController Detail1 和
  • 什么时候会使用没有 Arc 的互斥体?

    Rust 中一个极其常见的模式是Arc
  • 在 UITableViewCell 中进入编辑模式时隐藏 UITableViewCells(类似于联系人应用程序)

    有谁知道如何在进入编辑模式时隐藏分组 UITableView 中的多个单元格 我希望当退出编辑模式时 行能够以动画效果隐藏 如联系人应用程序中所示 如您所知 在联系人编辑模式下 行数比切换回正常模式时要多 我想知道如何顺利 切换 请注意 我
  • 结合多种功能

    我正在尝试制作一个 DNA 转录程序 但我的做法遇到了麻烦 我确信有一种更简单的方法可以做到这一点 但这是我想到的第一件事 但事实并非如此按照我想要的方式工作 dnaToRna Char gt Char dnaToRna dnaToRna
  • 使用 IntelliJ IDEA for JavaScript 的最佳插件和项目? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我正在使用 MEAN 堆栈构建一个 Web 应用程序 MongoDB http www mongodb com Express htt
  • 处理子资源完整性检查中的加载错误

    我正在实施子资源完整性检查 我想实现一个回退 以便 1 浏览器从我的 CDN 加载 执行完整性检查并继续 或者 2 如果完整性检查失败 嵌入式脚本将启动并从我的应用程序检索所需的脚本服务器 我控制的资源 我有一个简单的 javascript
  • 列出特定 AMI 的所有可能的实例类型?

    我知道以前曾有人问过这个问题 但我尚未找到用于获取给定 Amazon AMI 的可能实例类型列表的解决方法或解决方案 我正在使用 NET SDK 有没有人能够找到一种方法来做到这一点 这不可能 AMI 只是磁盘的映像 AWS 通常 可以检测
  • C#,“未将对象引用设置为对象的实例。”错误

    我有这个代码 namespace YellowBox public partial class Form1 Form private string sid FileTransferManager fm new FileTransferMan
  • UpsetR 更改图表中的集名称标签

    我正在尝试将 UpsetR 图中的集合名称标签 使用 Upset 函数 更改为多个单词的字符串 我希望将集合标签显示为 A 描述 B 描述 C 描述 而不是 A B C 作为集合标签 我不想在单词之间使用句号或下划线 test lt ups
  • 有没有办法在 PHP4 中模拟 PHP5 的 __call() 魔术方法?

    PHP5有一个 神奇的方法 call 可以在调用未定义方法时调用的任何类上定义 它大致相当于 Ruby 的method missing或者 Perl 的AUTOLOAD 在旧版本的 PHP 中可以做这样的事情吗 我缺少的最重要的一点是 ca
  • 修复未加引号的 PHP 数组键

    或者更确切地说 修复用作 PHP 数组键的未加引号的字符串 但这对于标题来说有点长 我继承了一个相当大的代码库 其中数组的编写方式如下 array id 0 array value test 虽然这段代码实际上有效 但它抛出了很多Use o
  • 计算 3D(或 n 维)质心的最佳方法是什么?

    作为工作项目的一部分 我必须计算 3D 空间中一组点的质心 现在我正在以一种看似简单但天真的方式来做这件事 通过取每组点的平均值 如下所示 centroid average x average y average z where x y a
  • 科学记数法 android java

    我用java为android编写了一个简单的计算器 我使用 double 作为变量 它给我的结果在达到一定数量的小数后以科学计数法表示 尽管仍然有足够的小数空间 有没有什么简单的方法可以将科学符号转换为 正常 符号 我现在可以分别用一个按钮
  • 如何查看node.js发送到服务器的请求?

    关于这个问题 在 Nodejs Protractor 中将 Cookie 从一个请求传输 传递到另一个请求 https stackoverflow com questions 42078780 transfer pass cookies f
  • PHP 中的标头会覆盖 HTTP 响应代码

    在 Apache 级别解决设置规则时 发现 php 中的 header Location filename php 覆盖了响应代码 看下面的代码 Expected result HTTP 1 1 308 永久重定向 主机 本地主机 8000
  • 如何显示 SVG 文件中的所有符号?

    我有一个 SVG 文件 如下所示
  • 将数据库初始化调用放入 C# 构造函数中可以吗? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我见过这是各种代码库 并且想知道这是否普遍不受欢迎 例如 public class MyClass public int Id public M
  • 为什么我必须在 Fortran 中隐式指定函数的双精度返回值?

    我是 Fortran 新手 我正在尝试common堵塞 我的代码很简单 program main implicit double precision p real 8 x y common yvalue y x 3d0 y 3d0 prin