2010-01-05 32 views
16

Tôi đang cố gắng thực hiện một cái gì đó là não chết đơn giản trong bất kỳ ngôn ngữ khác nhưng không javascript: nhận được các bit ra khỏi phao (và cách khác xung quanh).javascript float từ/đến bit

Trong C/C++ nó sẽ là một cái gì đó giống như

 
float a = 3.1415; 
int b = *((int*)&a); 

và ngược lại

 
int a = 1000; 
float b = *((float*)&a); 

Trong C# bạn có thể sử dụng BitConverter ... floatBits hoặc một cái gì đó giống nhau trong Java .. Ngay cả trong VB6 vì lợi ích của Chúa Kitô bạn có thể ghi nhớ một float32 vào một int32. Làm thế nào trên trái đất tôi có thể dịch giữa và int và một phao trong javascript?

+1

Xin chào, tôi chỉ muốn cảm ơn bạn đã trả lời câu hỏi của tôi khi hỏi bạn. Tôi cần biết cách chuyển đổi flaot/int trong C++; – LaikaN57

Trả lời

10

Bạn chắc chắn không nhận được bất kỳ thứ gì cấp thấp như vậy trong JavaScript. Nó sẽ cực kỳ nguy hiểm để cho phép recasting và con trỏ-frobbing trong một ngôn ngữ mà phải được an toàn cho các trang web tiềm năng không tin cậy kẻ tấn công để sử dụng.

Nếu bạn muốn nhận được một đại diện IEEE754 32 bit của một giá trị có độ chính xác duy nhất trong một số (mà nhớ không phải là một int; loại số duy nhất bạn nhận được trong JavaScript là double), bạn sẽ phải thực hiện nó cho mình bằng cách đánh lừa các dấu, số mũ và bit mantissa với nhau. Có mã ví dụ here.

+3

+1 để giới thiệu lại tôi với từ frobbing. –

+0

Chỉ cần xem Javascript trong trang babbage.cs.qc.edu - Nó có thể tạo ra câu trả lời đúng, và có thể hoạt động tốt trên máy tính trực tuyến, nhưng nó được viết khủng khiếp và không thích hợp để tái sử dụng theo ý kiến ​​của tôi. –

+4

Tôi không thấy lý do tại sao việc thêm chuyển đổi định dạng nhị phân IEEE gốc sang/từ số JavaScript sẽ là vấn đề bảo mật. Không có vấn đề gì liên quan đến vấn đề này. – akauppi

-1

Giống như các áp phích khác đã nói, JavaScript được nhập sai, vì vậy không có sự khác biệt trong các loại dữ liệu từ phao đến int hoặc ngược lại.

Tuy nhiên, những gì bạn đang tìm kiếm là

phao để int:

Math.floor(3.9); // result: 3 (truncate everything past .) or 
Math.round(3.9); // result: 4 (round to nearest whole number) 

Tùy thuộc vào bạn muốn. Trong C/C++ nó về cơ bản sẽ được sử dụng Math.floor để chuyển đổi sang số nguyên từ phao.

int nổi:

var a = 10; 
a.toFixed(3); // result: 10.000 
+0

do đó, mỗi lần lặp lại, bạn sẽ chọn 0,000000455 của một giây, câu chuyện thú vị bro –

+0

Đó không phải là những gì anh ta đang tìm kiếm. Anh ta đang tìm kiếm biểu diễn nhị phân của một đôi. Các '(int *) & a' trong câu hỏi cung cấp cho một con trỏ đến các bit cấp máy (IEEE) của đôi. – akauppi

2
function FloatToIEEE(f) 
{ 
    var buf = new ArrayBuffer(4); 
    (new Float32Array(buf))[0] = f; 
    return (new Uint32Array(buf))[0]; 
} 

Thật không may, điều này không làm việc với đôi và trong các trình duyệt cũ.

14
function DoubleToIEEE(f) 
{ 
    var buf = new ArrayBuffer(8); 
    (new Float64Array(buf))[0] = f; 
    return [ (new Uint32Array(buf))[0] ,(new Uint32Array(buf))[1] ]; 
} 
+1

Và hướng khác (từ byte sang phao), xem: http://stackoverflow.com/a/21282715/1691517. –

0
  1. JavaScript sử dụng double (IEEE 754) để đại diện cho tất cả các số
  2. double gồm [dấu, mũ (11bit), mantissa (52bit)] lĩnh vực. Giá trị của số được tính bằng công thức (-1)^sign * (1.mantissa) * 2^(exponent - 1023). (1.mantissa - có nghĩa là chúng ta hãy bit của mantissa thêm 1 ngay từ đầu và bước đi giá trị như số, ví dụ như nếu mantissa = 101 chúng tôi nhận được số 1.101 (bin) = 1 + 1/2 + 1/8 (dec) = 1.625 (dec)
  3. Chúng ta có thể nhận được giá trị của thử nghiệm sign chút nếu số là lớn hơn không.. có một vấn đề nhỏ với 0 đây vì double+0-0 giá trị, nhưng chúng ta có thể phân biệt được hai bằng cách tính 1/value và kiểm tra nếu giá trị là +Inf hoặc -Inf.
  4. Kể từ 1 <= 1.mantissa < 2 chúng ta có thể nhận được giá trị của mũ sử dụng Math.log2 ví dụMath.floor(Math.log2(666.0)) = 9 nên số mũ là exponent - 1023 = 9exponent = 1032, mà ở dạng nhị phân là (1032).toString(2) = "10000001000"
  5. Sau khi chúng tôi nhận mũ chúng ta có thể mở rộng số bằng không mũ mà không thay đổi mantissa, value = value/Math.pow(2, Math.floor(Math.log2(666.0))), bây giờ giá trị đại diện cho số (-1)^sign * (1.mantissa). Nếu chúng ta bỏ qua dấu và nhân số đó với 2^52 chúng ta nhận được giá trị số nguyên có cùng bit như 1.mantissa: ((666/Math.pow(2, Math.floor(Math.log2(666)))) * Math.pow(2, 52)).toString(2) = "10100110100000000000000000000000000000000000000000000" (chúng ta phải bỏ qua hàng đầu 1).
  6. Sau một chuỗi concat của bạn sẽ nhận được những gì bạn muốn

Đây chỉ là bằng chứng của khái niệm, chúng tôi đã không thảo luận về số denormalized hoặc các giá trị đặc biệt như NaN - nhưng tôi nghĩ rằng nó có thể được mở rộng vào tài khoản cho những trường hợp này.

@bensiu câu trả lời là tốt, nhưng nếu thấy mình sử dụng một số thông dịch viên JS cũ, bạn có thể sử dụng phương pháp này.

Các vấn đề liên quan