2

私はいくつかの 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 コマンドを使用して出力値を比較すると、まったく異なる結果が表示されます。

Fortran REAL に相当するものを PHP の char[4] 配列にパックする正しい方法は何ですか?

4

2 に答える 2

1

それは非常に単純であることが判明しました。

FORTAN REAL は、IEEE 754 32 ビット浮動小数点数として格納されます。

あなたの出力odは誤解を招くものでした。これを 16 進数に変換すると、次のようになります。

0115040 0134631 0005077

0x20, 0x9A, 0x99, 0xB9, 0x3f, 0x0a

ファイルの最初と最後のバイトは冗長で、それぞれスペースと改行です。求めているビットは、中央の 4 バイトです。

packfloat から変換できます (警告- エンディアンマシンに依存します) 。

以下:

var_dump(bin2hex(pack('f', 1.450)));

おなじみのバイト シーケンスが得られます。

string(8) "9a99b93f"

そのため、16 進数に変換する代わりに、最初にスペースがあり、最後にキャリッジ リターンがあるファイルに出力すると、同じファイルが得られます。(PHP/マシン構成がフロートで異常なことをしない限り - ただし、IEEE 754 仕様に従っていれば、それを再現できるはずです)

于 2012-08-08T16:00:02.267 に答える
0

これは、回答ではなく拡張コメントである可能性があります。

あなたは、声明の中で

CALL MKS1(x,a)

サブルーチンが4つの長さ1文字の配列を予期する場合にREAL引数を渡します。あなたはあなたに起こるすべての悪いことをするに値します:-)あなたはあなたのサブルーチンに明示的なインターフェースを必要としないのでこれをコンパイルすることができるだけです。

PHPプログラムが読み取る4文字をどのようにしますか?たとえば、FortranがREALバイナリファイルの4バイトに書き込み、PHPが4バイトを4つの単一文字として読み取った場合、必要な文字を取得できますか?あなたの要件が何であるかわかりません。

于 2012-08-08T15:32:15.237 に答える