2009-06-27 2 views
2

내가 정말로해야할 것은 정밀도 손실없이 부동 소수점 숫자를 C로 내보내는 것이다.파이썬 2.5에서 파이썬 부동 소수점을 16 진수 문자열로 변환하려면 어떻게해야합니까? Nothing working solution attached

import math 
import struct 
x = math.sqrt(2) 
print struct.unpack('ii', struct.pack('d', x)) 
# prints (1719614413, 1073127582) 

을 그리고 C에서 나는이 시도 :

내가 파이썬에서 이런 짓을

#include <math.h> 
#include <stdio.h> 

int main(void) 
{ 
    unsigned long long x[2] = {1719614413, 1073127582}; 
    long long lx; 
    double xf; 

    lx = (x[0] << 32) | x[1]; 
    xf = (double)lx; 
    printf("%lf\n", xf); 
    return 0; 
} 

을하지만 C에서 내가 얻을 :

7385687666638364672.000000하지 SQRT (2).

무엇이 누락 되었습니까?

감사합니다.

+0

좋아, 나는 내 C에서 녹슬지 만 확실히 그렇긴하지만 문자열로 내보내고 C에서 이중으로 변환하는 것이 잘못된 이유는 무엇입니까? –

답변

6

파이썬 코드가 작동하는 것 같습니다. 문제는 C 코드에 있습니다. 바로 long long을 입력했지만 double으로 재 해석하지 않고 정수 값을 직접 부동 소수점으로 변환합니다. 당신은 몇 가지 포인터를 던질 경우/그것을 해결 그것을 작동 : double (및 float에 대한)에 대한 형식 지정이 %f하지 %lf입니다

jkugelman$ cat float.c 
#include <stdio.h> 

int main(void) 
{ 
    unsigned long x[2] = {1719614413, 1073127582}; 
    double d = *(double *) x; 

    printf("%f\n", d); 
    return 0; 
} 
jkugelman$ gcc -o float float.c 
jkugelman$ ./float 
1.414214 

주의 사항도있다. %lflong double입니다.

+0

나는 (나사를 뽑기 전에) 오래 걸려서 무슨 일이 일어 났는지 알았어! 저는 64 비트 (AMD64)와 sizeof (long) == 8을 사용하고 있습니다. 그래서 여기에 unsigned int를 사용해야합니다. 감사합니다. –

+0

@Nelson : 이식성을 위해서는 플랫폼에서 올바른 크기가 아닌 크기 정의 유형을 사용해야합니다. int는 32 비트가 될 것이라는 보장이 없습니다. C99 표준은 double이 표준 64 비트 IEEE double 인 모든 플랫폼에서 작동하는 uint32_t (stdint.h의)와 같은 유형을 정의합니다. 파이썬 측면에서 구조체 문자열 앞에 "="접두사를 붙이면 항상 고정 된 크기 (예 : "I"= 32 비트 부호없는 int)를 사용하거나 고정 된 엔디안을 사용하는 "<" or ">"("="은 기본 엔디안을 사용하므로 C 컴파일러와 일치). – Brian

3

당신이 리틀 엔디안 아키텍처를 대상으로하는 경우,

>>> s = struct.pack('<d', x) 
>>> ''.join('%.2x' % ord(c) for c in s) 
'cd3b7f669ea0f63f' 

빅 엔디안은 대신 <d'>d'를 사용하는 경우. 두 경우 모두, 질문 제목에서 질문하는 것처럼 16 진수 문자열을 제공하고 물론 C 코드가이를 해석 할 수 있습니다. 나는이 두 int가 "16 진수 문자열"과 무슨 관계가 있는지 알지 못합니다.

+0

Alex, 귀하의 의견에 감사드립니다. 귀하의 답변도 도움이됩니다. 실제로 필요한 것은 C (코드 생성)로 내보내는 것이 었습니다. 그래서 0xcd3b7f669ea0f63f (long long C)를 사용할 수 있습니다 ... –

+0

음, 나는 엔디안을 신경 쓸 필요가 없도록 숫자를 사용하는 것을 선호하지만 도움이됩니다. –

+0

endianness에 관심을 가져야합니다 - 두 개의 32 비트 숫자는 어떤 순서로 배치합니까? –

1

repr()은 (는) 친구입니다.

C:\junk\es2>type es2.c 
#include <stdio.h> 
#include <math.h> 
#include <assert.h> 

int main(int argc, char** argv) { 
    double expected, actual; 
    int nconv; 
    expected = sqrt(2.0); 
    printf("expected: %20.17g\n", expected); 
    actual = -666.666; 
    nconv = scanf("%lf", &actual); 
    assert(nconv == 1); 
    printf("actual: %20.17g\n", actual); 
    assert(actual == expected); 
    return 0; 
    } 


C:\junk\es2>gcc es2.c 

C:\junk\es2>\python26\python -c "import math; print repr(math.sqrt(2.0))" | a 
expected: 1.4142135623730951 
actual:  1.4142135623730951 

C:\junk\es2>