2009-10-20 4 views
8

으로 변환합니다. "4072508200000000"의 16 진수가 있다고 가정하고 IEEE-754 이중 형식의 부동 소수점 숫자 (293.03173828125000)를 원한다고 가정합니다. 자바 스크립트 변수에 넣는다.IEEE-754 double의 16 진수 표현을 사용하는 문자열을 JavaScript 숫자 변수

일부 마스킹과 pow() 호출을 사용하는 방법을 생각할 수 있지만 더 간단한 해결책이 있습니까?

클라이언트 측 솔루션이 필요합니다.

도움이 될 수 있습니다. IEEE-754의 16 진수 인코딩을 입력하고 가수와 지수를 분석 할 수있는 웹 사이트입니다.

http://babbage.cs.qc.edu/IEEE-754/64bit.html

명 항상 "왜?"여기 물어 경향이 있기 때문에

이유 : 나는 구글의 Procol 버퍼 (protobuf)의 기존의 불완전한 구현을 작성하기 위해 노력하고있어.

+0

개인적으로는 정규 표현식을 사용하여 16 진수 값을 분리하여 시작합니다. 그런 다음 정수로 평가하고 마지막으로 다시 플로트로 변환하려고합니다. Javascript 런타임이 길을 따라 조금도 잃어 버리지 않도록해야 할 것이기 때문에 이것은 까다로울 것 같습니다. – Pointy

+0

최대의 휴대 성을 위해 IEEE-754 double이 빅 엔디 언 또는 리틀 엔디안이 될 수 있다고 간주해야합니다. 16 진수 입력에 사용되는 규칙을 알고있는 경우 pow()를 사용하는 클라이언트 측 솔루션은 이식 가능해야합니다. 일종의 타입 펀칭 접근법을 사용하기로 결정했다면, 클라이언트 플랫폼의 두배를위한 엔디안을 먼저 확인해야합니다. –

+0

@Jim Lewis : 나는 크고 작은 엔디 언을 말해주는 깃발이 있습니다. – Nosredna

답변

10

나는 좋은 방법을 모른다. 확실히 여기 완전히 자바 스크립트 내에서 단일 정밀도 예입니다, 어려운 방법을 수행 할 수 있습니다의 제조 구현은 대부분의 필드는 일반적으로에 대한 특별한 해석을 지정하여 구현, 마법 값이 있음을 고려해야한다

js> a = 0x41973333 
1100428083 
js> (a & 0x7fffff | 0x800000) * 1.0/Math.pow(2,23) * Math.pow(2, ((a>>23 & 0xff) - 127)) 
18.899999618530273 

무엇 가장 크거나 작았을 것이다. 따라서 NaN 및 무한을 감지하십시오. 위의 예는 네거티브를 확인해야합니다. (a & 0x80000000)

업데이트 : 그래, 나도 두 배로 늘었습니다. 내부 JS 표현이 double이기 때문에 위의 기술을 직접 확장 할 수 없으므로이 정의로 인해 길이가 52 인 비트 열을 처리 할 수 ​​있으며 전혀 32 개 이상 이동할 수 없습니다.

좋아, 먼저 을 두 번 잘라 내기 문자열 낮은 8 자리 또는 32 비트로 잘라냅니다. 그것들을 별도의 객체로 처리하십시오. 그 다음 :

js> a = 0x40725082  
1081233538 
js> (a & 0xfffff | 0x100000) * 1.0/Math.pow(2, 52 - 32) * Math.pow(2, ((a >> 52 - 32 & 0x7ff) - 1023)) 
293.03173828125 
js> 

나는 그것이 OP에서 왔기 때문에 위의 예를 유지했다. 좀 더 어려운 경우는 하위 32 비트에 값이있는 경우입니다.

js> a = 0x40725082 
1081233538 
js> b = 0xdeadbeef 
3735928559 
js> e = (a >> 52 - 32 & 0x7ff) - 1023 
8 
js> (a & 0xfffff | 0x100000) * 1.0/Math.pow(2,52-32) * Math.pow(2, e) +   
    b * 1.0/Math.pow(2, 52) * Math.pow(2, e) 
293.0319506442019 
js> 

는 당신이 밖으로 인수 분해 할 수있는 몇 가지 명백한 표현식이 있습니다하지만 당신이 형식에 관련이 있는지 볼 수 있도록 내가이 길을 떠 났어요 : 여기 0x40725082deadbeef의 전환, 이중 전체의 정밀도입니다.

+0

마지막 예는 0x40725082deadbeef의 링크 된 사이트에 동의합니다. – DigitalRoss

+0

아주 좋네요. 감사. – Nosredna

+0

왜이 코드 (두 번째 예)가 a = 0 일 때'1.1125369292536007e-308'을 반환합니까? – etuardu

4

Google을 통해이 페이지를 찾는 사람들을 위해 DigitalRoss 솔루션에 빠르게 추가되었습니다.

s = a >> 31 ? -1 : 1 

당신은 다음 s을 포함 할 수 있습니다 : 나는에 입력을 싶지만위한 +/- 무한대 및 NaN의 가장자리의 경우, 별도로

, 당신은 또한 계정에 결과의 부호를 취할 필요 최종 곱셈에서 정확한 결과를 얻으십시오.

리틀 엔디안 솔루션을 사용하려면 ab의 비트를 반대로 변환해야합니다.

1

새로운 Typed Arrays 메커니즘은이 작업을 수행 할 수 있습니다 (그리고 아마도 프로토콜 버퍼를 구현하기위한 이상적인 메커니즘) :

var buffer = new ArrayBuffer(8); 
var bytes = new Uint8Array(buffer); 
var doubles = new Float64Array(buffer); // not supported in Chrome 

bytes[7] = 0x40; // Load the hex string "40 72 50 82 00 00 00 00" 
bytes[6] = 0x72; 
bytes[5] = 0x50; 
bytes[4] = 0x82; 
bytes[3] = 0x00; 
bytes[2] = 0x00; 
bytes[1] = 0x00; 
bytes[0] = 0x00; 

my_double = doubles[0]; 

document.write(my_double); // 293.03173828125 

이 리틀 엔디안 기계를 가정합니다.

불행히도 Float32Array은 있지만 크롬에는 Float64Array이 없습니다. 위 예제는 Firefox 4.0.1에서 작동합니다.