【问题标题】:Long ints in FortranFortran 中的长整数
【发布时间】:2010-07-08 14:26:37
【问题描述】:

我正在尝试处理大数(~10^14),我需要能够存储它们并迭代该长度的循环,即

n=SOME_BIG_NUMBER
do i=n,1,-1

我尝试了通常的星号,kind=8 等,但似乎没有任何效果。 然后我检查了huge内部函数,代码:

program inttest

print *,huge(1)
print *,huge(2)
print *,huge(4)
print *,huge(8)
print *,huge(16)
print *,huge(32)

end program inttest

在所有情况下都生成数字 2147483647。为什么是这样?我在 64 位机器上使用 gfortran (f95)。

如果我需要一个 bignum 库,人们会推荐哪一个?

【问题讨论】:

  • 您是否将变量声明为 integer*8 ?
  • 循环迭代~10^14 次?你知道这需要多长时间吗?我认为你需要重新考虑你的算法。

标签: loops fortran largenumber


【解决方案1】:

我在 Mac 上使用的 gfortran 版本 4.3、4.4 和 4.5 支持 8 字节整数。在 Fortran >= 90 中选择变量类型的最佳方法是使用内部函数来指定所需的精度。试试:

integer, parameter :: LargeInt_K = selected_int_kind (18)
integer (kind=LargeInt_K) :: i, n

获取至少 18 位十进制数字,通常为 8 字节整数。

使用gfortran 4.3,huge(1_LargeInt_K)输出9223372036854775807。当你写huge(1)等时,默认常量是默认整数,这里显然是4字节,因为huge返回2147483647。所以有时你需要指定常量的精度,而不仅仅是变量 - 更常见的是,当人们在一个实数常量(默认为单精度)上丢失重要数字时,这会让人绊倒。

另见Fortran: integer*4 vs integer(4) vs integer(kind=4)

通常 gfortran 具有命令名称 gfortran。 f95 可以是不同的编译器吗?试试“gfortran -v”和“f95 -v”。

【讨论】:

  • 谢谢。我没有意识到巨大的工作是这样的,但现在很明显。我刚刚发现我的主要问题不是我的文字,我会写 n=123456...9 (kind=blah)。写 n=12...9_long where long=selected_int_kind(13) 工作正常。
  • gfortran 编译时警告选项之一将通知您常量太大。尝试: -fimplicit-none -Wall -Wline-truncation -Wcharacter-truncation -Wsurprising -Waliasing -Wimplicit-interface -Wunused-parameter -fcheck=all -fbacktrace 用于 gfortran 4.5。或 -fbounds-check 用于早期版本,而不是 -fcheck-all
【解决方案2】:

您误解了HUGE 函数的精确定义。 HUGE(num) 返回与num 相同种类和类型的最大数字。返回的值也具有与num 相同的种类和类型。由于您的所有输入值都是(默认)整数HUGE,因此正确地返回最大的默认大小整数。

HUGE(num) 不返回具有kind=num 的最大整数。 HUGE(num) 也不会返回以 num 字节表示的最大数字。虽然许多编译器使用 integer(kind=4)integer(kind=8) etc 来表示 4 字节和 8 字节整数,但语言标准并不能保证这一点,并且不能依赖于可移植性。

@MSB 的回答告诉你如何做你想做的事,我只是在做一些澄清。

【讨论】:

    【解决方案3】:

    总结:考虑查看编译器选项。

    自从我完成 FORTRAN 以来已经过去了一段时间,我不记得使用过 HUGE(),但我看了一点。我的 Intel Linux 机器有 gfortran 4.1.2。我发现我必须在打开 -fdefault-integer-8 选项的情况下进行编译,以使其适用于 64 位整数。具体来说,使用以下代码:

          program inttest
          print *, huge(1)
          end program inttest
    

    运行

    $ gfortran inttest.for

    创建了一个打印出来的可执行文件:

    2147483647

    但是,运行:

    $ gfortran -fdefault-integer-8 inttest.for

    产生了一个可执行文件,它给出了输出:

    9223372036854775807

    另外,当我将一个变量声明为 integer*8 并在没有 -fdefault-integer-8 选项的情况下编译时,我得到了一个错误。代码:

      program inttest2
      integer*8  test_int
      test_int = 9223372036854775807
      print *, test_int
      end program inttest2
    

    运行

    $ gfortran inttest2.for

    导致

    在文件 inttest.for:4 中

      test_int = 9223372036854775807  
                                   1 
    

    错误:整数对于 (1) 处的同类而言太大

    但是,当我使用 -fdefault-integer-8 选项进行编译并得到一个打印的可执行文件时,一切正常

    9223372036854775807

    也许还有其他有用的 gfortran 选项,但我没有进一步调查。

    当然,这仍然不能让您获得 10^14,但它可能有助于解释您看到的结果。

    【讨论】:

    • 选项 -fdefault-integer-8 将默认整数设置为 8 字节,并不是必须能够使用 8 字节整数;它们可以通过声明获得。错误消息“Error: Integer too big for its kind at (1)”告诉您常量 9223372036854775807 对于它的类型来说太大了。您不需要将默认整数类型设置为 8 个字节来解决该问题——您可以指定常量的类型。
    • @M. S.B.:谢谢你的解释。如何指定常量类型?
    • 常量的类型用下划线后跟一个种类值来指定:9223372036854775807_KindValue。最好使用内在的 selected_int_kind (对于整数,或 selected_real_kind 对于实数)来定义整数/参数“变量” KindValue(请参阅此问题的答案),而不是依赖于特定的数值,例如 8,它可以在编译器之间的含义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-14
    • 2022-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多