我的任务是将一些Fortran代码转换为PHP,并且遇到了最后一道障碍。
本质上,Fortran将REAL转换为二进制CHAR(4),最终写入文件。
Fortran(也让我感到困惑)如下:
FUNCTION MKS(x)
CHARACTER (LEN=4) :: MKS ! The 4-character string which is returned to
REAL :: x ! The incoming single-precision variable
CHARACTER (LEN=1), DIMENSION(4) :: a ! A working variable
CHARACTER (LEN=4) :: d ! A working variable
CALL MKS1(x,a) ! Send x - get back a(1), a(2), a(3), a(4)
! Note: x will hold the first 32 bits referenced
! and a will hold the next 32 bits
d = a(1) // a(2) // a(3) // a(4) ! concatenate into 1 string (d)
MKS = d ! assign string to variable MKS
END FUNCTION MKS
SUBROUTINE MKS1 (b,c)
IMPLICIT NONE
CHARACTER (LEN=1), DIMENSION(4) :: b ! array with incoming 32 bits
CHARACTER (LEN=1), DIMENSION(4) :: c ! array with each character returned
INTEGER :: i ! DO Loop counter
DO i=1,4
c(i) = b(i)
END DO
END SUBROUTINE MKS1
我试图使用php重新创建此功能,如下所示
pack('CCCC', $value & 0x000F,
($value>>8) & 0x000F,
($value>>16) & 0x000F,
($value>>24) &0x000F);
但是使用* nix od命令比较输出值会显示完全不同的结果。
在PHP中将Fortran REAL的等价物打包成char [4]数组的正确方法是什么?
答案 0 :(得分:1)
结果很简单。
您的FORTAN REAL存储为IEEE 754 32位浮点数。
od
的输出具有误导性。将其转换为十六进制给出以下内容。
0115040 0134631 0005077
0x20, 0x9A, 0x99, 0xB9, 0x3f, 0x0a
文件的第一个和最后一个字节是冗余的,它们分别是空格和回车符。我们所追求的是中间的4个字节。
使用pack
我们可以转换浮点数(警告 - 字节顺序 依赖于机器)。
以下内容:
var_dump(bin2hex(pack('f', 1.450)));
给我们一个熟悉的字节序列。
string(8) "9a99b93f"
因此,不是转换为十六进制,而是将其输出到开头有空格并且末尾有回车符的文件,并且您将拥有相同的文件。 (只要您的PHP /机器配置不会对浮点数做些什么 - 但即使这样,如果您遵循IEEE 754规范,您也应该能够重现它)
答案 1 :(得分:0)
这可能是一个扩展的评论而不是答案。
你在声明中
CALL MKS1(x,a)
传递一个REAL参数,其中子例程需要一个4个长度为1个字符的数组。你应该得到发生在你身上的所有不好的事情:-)你只能编译它,因为你没有在你的子程序上需要显式接口。
您希望PHP程序读取的4个字符是什么?例如,如果您的Fortran将REAL
写入二进制文件中的4个字节,并且您的PHP读取4个字节作为4个单个字符,那么您是否会获得所需的字符?我不确定你的要求是什么。