Tôi đã kiểm tra một thư viện vật lý trò chơi trực tuyến ngày hôm nay và tình cờ thấy nhà điều hành ~ ~. Tôi biết một đơn ~ là một chút KHÔNG, điều đó sẽ làm cho ~ ~ KHÔNG phải là KHÔNG, mà sẽ trả lại cùng một giá trị, phải không?
Tôi đã kiểm tra một thư viện vật lý trò chơi trực tuyến ngày hôm nay và tình cờ thấy nhà điều hành ~ ~. Tôi biết một đơn ~ là một chút KHÔNG, điều đó sẽ làm cho ~ ~ KHÔNG phải là KHÔNG, mà sẽ trả lại cùng một giá trị, phải không?
Câu trả lời:
Nó loại bỏ mọi thứ sau dấu thập phân vì các toán tử bitwise ngầm chuyển đổi toán hạng của chúng thành các số nguyên 32 bit đã ký. Điều này hoạt động cho dù các toán hạng là số (dấu phẩy động) hoặc chuỗi và kết quả là một số.
Nói cách khác, nó mang lại:
function(x) {
if(x < 0) return Math.ceil(x);
else return Math.floor(x);
}
chỉ khi x nằm giữa - (2 31 ) và 2 31 - 1. Nếu không, tràn sẽ xảy ra và số sẽ "bao quanh".
Điều này có thể được coi là hữu ích để chuyển đổi đối số chuỗi của hàm thành số, nhưng cả hai vì khả năng tràn và không chính xác khi sử dụng với người không có số nguyên, tôi sẽ không sử dụng cách đó ngoại trừ "mã golf" ( nghĩa là cắt xén các byte một cách vô nghĩa khỏi mã nguồn của chương trình của bạn với chi phí dễ đọc và mạnh mẽ). Tôi sẽ sử dụng +xhoặc Number(x)thay vào đó.
Số -43.2, ví dụ:
-43,2 10 = 1111111111111111111111111111010101 2 2
dưới dạng số nhị phân 32 bit đã ký (bổ sung hai). (JavaScript bỏ qua những gì sau dấu thập phân.) Đảo ngược các bit cho:
KHÔNG -43 10 = 00000000000000000000000000101010 2 = 42 10
Đảo ngược một lần nữa cho:
KHÔNG 42 10 = 11111111111111111111111111010101 2 = -43 10
Điều này khác với Math.floor(-43.2)các số âm được làm tròn về 0, không cách xa nó. (Hàm sàn, sẽ bằng -44, luôn làm tròn xuống số nguyên thấp hơn tiếp theo, bất kể số đó là dương hay âm.)
~~là một cách tốc ký (và có thể là một giải pháp tốt?) Để tạo ra một chức năng cắt ngắn , nhưng rõ ràng là trong javascript .
~~.
Toán tử ~ đầu tiên buộc toán hạng thành một số nguyên (có thể sau khi ép giá trị thành chuỗi hoặc boolean), sau đó đảo ngược 31 bit thấp nhất. Chính thức các số ECMAScript đều là dấu phẩy động, nhưng một số số được triển khai dưới dạng số nguyên 31 bit trong công cụ SpiderMonkey.
Bạn có thể sử dụng nó để biến mảng 1 phần tử thành số nguyên. Điểm nổi được chuyển đổi theo quy tắc C, nghĩa là. cắt ngắn của phần phân đoạn.
Toán tử thứ hai ~ sau đó đảo ngược các bit trở lại, vì vậy bạn biết rằng bạn sẽ có một số nguyên. Điều này không giống như ép buộc một giá trị thành boolean trong một câu lệnh điều kiện, bởi vì một đối tượng trống {} đánh giá là đúng, trong khi ~ ~ {} đánh giá là sai.
js>~~"yes"
0
js>~~3
3
js>~~"yes"
0
js>~~false
0
js>~~""
0
js>~~true
1
js>~~"3"
3
js>~~{}
0
js>~~{a:2}
0
js>~~[2]
2
js>~~[2,3]
0
js>~~{toString: function() {return 4}}
4
js>~~NaN
0
js>~~[4.5]
4
js>~~5.6
5
js>~~-5.6
-5
~~undefined // 0
~~null // 0
~làm những gì bạn mô tả đầu tiên ~làm và ngược lại. Các ~nhà điều hành là một nhà khai thác unary và được interpereted từ phải sang trái ~~Xcũng giống như ~(~X)không thích (~~)X(mà sẽ là một lỗi cú pháp)
Trong ECMAScript 6, tương đương với ~~là Math.trunc :
Trả về phần tích phân của một số bằng cách loại bỏ bất kỳ chữ số phân số nào. Nó không làm tròn bất kỳ số nào.
Math.trunc(13.37) // 13
Math.trunc(42.84) // 42
Math.trunc(0.123) // 0
Math.trunc(-0.123) // -0
Math.trunc("-1.123")// -1
Math.trunc(NaN) // NaN
Math.trunc("foo") // NaN
Math.trunc() // NaN
Các polyfill:
function trunc(x) {
return x < 0 ? Math.ceil(x) : Math.floor(x);
}
Việc này ~dường như để làm -(N+1). Vì vậy, ~2 == -(2 + 1) == -3nếu bạn làm lại trên -3, nó sẽ quay lại: ~-3 == -(-3 + 1) == 2Nó có thể chỉ chuyển đổi một chuỗi thành một số theo cách vòng.
Xem chủ đề này: http://www.sitepoint.com/forums/showthread.php?t=663275
Ngoài ra, thông tin chi tiết hơn có sẵn ở đây: http://dreaminginjavascript.wordpress.com/2008/07/04/28/
Đưa ra ~Nlà -(N+1), ~~Nlà sau đó -(-(N+1) + 1). Mà, rõ ràng, dẫn đến một thủ thuật gọn gàng .
Chỉ là một chút cảnh báo. Các câu trả lời khác ở đây khiến tôi gặp một số rắc rối.
Mục đích là để loại bỏ bất cứ thứ gì sau dấu thập phân của số dấu phẩy động, nhưng nó có một số trường hợp góc làm cho nó trở thành một lỗi nguy hiểm. Tôi khuyên bạn nên tránh ~ ~.
Đầu tiên, ~ ~ không hoạt động với số lượng rất lớn.
~~1000000000000 == -727279968
Cách khác, sử dụng Math.trunc()(như Gajus đã đề cập, Math.trunc()trả về phần nguyên của số dấu phẩy động nhưng chỉ khả dụng trong JavaScript tuân thủ ECMAScript 6). Bạn luôn có thể tự tạo cho riêng mình Math.trunc()các môi trường không phải ECMAScript-6 bằng cách này:
if(!Math.trunc){
Math.trunc = function(value){
return Math.sign(value) * Math.floor(Math.abs(value));
}
}
Tôi đã viết một bài đăng trên blog này để tham khảo: http://bitlords.blogspot.com/2016/08/the-double-tilde-x-technique-in.html
Dưới đây là một ví dụ về cách sử dụng toán tử này một cách hiệu quả, nơi sử dụng hợp lý:
leftOffset = -(~~$('html').css('padding-left').replace('px', '') + ~~$('body').css('margin-left').replace('px', '')),
Nguồn:
Chuyển đổi chuỗi thành số
console.log(~~-1); // -1
console.log(~~0); // 0
console.log(~~1); // 1
console.log(~~"-1"); // -1
console.log(~~"0"); // 0
console.log(~~"1"); // 1
console.log(~~true); // 1
console.log(~~false); // 0
~ -1 là 0
if (~someStr.indexOf("a")) {
// Found it
} else {
// Not Found
}
Tilde (~) có một algorihm - (N + 1)
Đối với kỳ thi:
~0 = -(0+1) = -1
~5 = -(5+1) = -6
~-7 = -(-7+1) = 6
Dấu ngã kép là - (- (N + 1) +1)
Ví dụ:
~~5 = -(-(5+1)+1) = 5
~~-3 = -(-(-3+1)+1) = -3
Dấu ngã ba là - (- (- (N + 1) +1) +1)
Ví dụ:
~~~2 = -(-(-(2+1)+1)+1) = -3
~~~3 = -(-(-(3+1)+1)+1) = -4