{"id":367,"date":"2011-03-13T16:35:04","date_gmt":"2011-03-13T22:35:04","guid":{"rendered":"http:\/\/bateru.com\/news\/?p=367"},"modified":"2011-03-15T01:46:32","modified_gmt":"2011-03-15T07:46:32","slug":"javascript-not-is-not-what-you-expect","status":"publish","type":"post","link":"https:\/\/bateru.com\/news\/2011\/03\/javascript-not-is-not-what-you-expect\/","title":{"rendered":"Javascript NOT is not what you expect"},"content":{"rendered":"<p><div class=\"imagecaptioneasy imagecaptioneasy_top_nowrap\" style=\"width:px;\"><img decoding=\"async\" src=\"http:\/\/bateru.com\/news\/wp-content\/uploads\/2011\/03\/NOT-GATE-300x129.png\" alt=\"Not gate\"\/><br style=\"clear:both\" \/><span>Not gate<\/span><\/div><br \/>\nA weird part of javascript is trying to toggle the bits in a number. For most programming languages, like C and Java, ~ represents a bitwise NOT operation, aka one&#8217;s complement. But in javascript, ~ produces the two&#8217;s complement. Since ~num gives the two&#8217;s complement, equivalent to -(num + 1), then one would suspect that ~(num -1) should give back the one&#8217;s complement.<br \/>\nHowever that&#8217;s not the case, as the next example demonstrates.<\/p>\n<pre lang='javascript' line='1'>\r\nvar num = 9;\r\nnum.toString(2);            \/\/returns 1001\r\n(~num).toString(2);\t\/\/ returns \"-1010\"\r\n~(num - 1).toString(2);    \/\/returns \"-1001\"\r\n<\/pre>\n<p>As you can see from the example, there are two main problems. The first is that the sign bit is replaced with a negative sign. And second, the bits don&#8217;t get toggled.<br \/>\nTo fix this problem most programmers would just XOR the number with a mask to toggle the bits. Although this works, it quickly produces the unintended result once you XOR a number larger than the mask.<br \/>\n<b>Example:<\/b><\/p>\n<pre lang='javascript' line=\"1\">\r\nvar BIT_MASK = 0xF;\r\n(9).toString(2);\t\t\t\/\/returns \"1001\"\r\n(9 ^ BIT_MASK).toString(2);\t\t\/\/returns \"110\"\r\n(30).toString(2);\t\t\t\/\/returns \"11110\"\r\n(30 ^ BIT_MASK).toString(2);\t\t\/\/returns \"10001\"\r\n<\/pre>\n<p>A simple solution to this problem is to not to use javascript for bitwise operations.<br \/>\nHowever, if javascript is required then use the following code to implement bitwise NOT operation.<br \/>\n<b>Method 1:<\/b> Simple approach.<\/p>\n<pre lang='javascript' line=\"1\">\r\nvar toggleBits = function( dec ){\r\n    var mask = 0xFFFFFFF;\r\n    return ( dec ^ mask ).toString(2).match( RegExp( \"[01]{\"+(dec.toString(2).length)+\"}$\" ) )[0];\r\n};\r\n\r\nvar num = 23;\r\nnum.toString(2);\t\t\/\/ returns 10111\r\nnum = toggleBits(num);\t        \/\/ num = 01000;\r\nnum = parseInt( num, 2);\t\/\/ num = 8, binary = 1000\r\n<\/pre>\n<p><b>Method 2:<\/b> More advance features.<\/p>\n<pre lang='javascript' line='1'>\r\n\/\/ Programer: Larry Battle\r\n\/\/ Purpose: Provide a bit toggle function for javascript.\r\nvar getStrCopy = function (str, copies) {\r\n\tvar newStr = str;\r\n\tcopies = (copies > 0) ? copies : 1;\r\n\twhile (--copies) {\r\n\t\tnewStr += str;\r\n\t}\r\n\treturn newStr;\r\n};\r\nvar convertDecToBase = function ( dec, base, length, padding ) {\r\n\tpadding = padding || '0' ;\r\n\tvar num = dec.toString( base );\r\n\tlength = length || num.length;\r\n\tif (num.length !== length) {\r\n\t\tif (num.length > length) {\r\n\t\t\tthrow new Error(\"convertDecToBase(): num(\" + num + \") > length(\" + length + \") too long.\");\r\n\t\t}\r\n\t\tnum = getStrCopy( padding, (length - num.length)) + num;\r\n\t}\r\n\treturn num;\r\n};\r\nvar formatBinaryStr = function( str ){\r\n    return str.replace( \/\\d{4}\/g, '$& ' ).replace( \/\\s$\/,'');\r\n};\r\nvar toggleBits = function( dec, length, doFormat ){\r\n    var str = convertDecToBase( dec, 2, length || 8 );\r\n    var binaryStr = str.replace( \/0\/g, 'o' ).replace( \/1\/g, '0').replace( \/o\/g, '1' );\r\n    return ( doFormat ) ? formatBinaryStr( binaryStr ) : binaryStr ;\r\n};\r\n\r\n\/\/ The following requires Firebug or Google Chrome Dev Tools\r\nclear();\r\n\r\n\/\/ Test case\r\nvar num = 230;\r\nvar testNum = parseInt( toggleBits(num), 2 );\r\ntestNum = parseInt( toggleBits( testNum ), 2 );\r\nconsole.log( \"(Test Case) 2 Bit Toggles will give the original number: \" +  (testNum == num) );\r\n\r\n\/\/ Examples: \r\nconsole.log( toggleBits( 1 ) );    \/\/ displays \"11111110\"\r\nconsole.log( toggleBits( 2 ) );    \/\/ displays \"11111101\"\r\nconsole.log( toggleBits( 50, 16 ) );\/\/ displays \"1111111111001101\"\r\nconsole.log( toggleBits( 15, 8, true ) );    \/\/ displays \"1111 0000\"\r\nconsole.log( toggleBits( 520, 16, true ) ); \/\/ displays \"1111 1101 1111 0111\"\r\n<\/pre>\n<p>\nFor more information check out <a href=\"https:\/\/developer.mozilla.org\/en\/JavaScript\/Reference\/Operators\/Bitwise_Operators\">Mozilla&#8217;s Bitwise Operators Reference<\/a><\/p>\n<p><iframe style=\"float:right;\" src=\"http:\/\/rcm.amazon.com\/e\/cm?t=baterucom-20&#038;o=1&#038;p=8&#038;l=as1&#038;asins=B0002CE0XY&#038;ref=qf_sp_asin_til&#038;fc1=000000&#038;IS2=1&#038;lt1=_blank&#038;m=amazon&#038;lc1=0000FF&#038;bc1=000000&#038;bg1=FFFFFF&#038;f=ifr\" style=\"width:120px;height:240px;\" scrolling=\"no\" marginwidth=\"0\" marginheight=\"0\" frameborder=\"0\"><\/iframe><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Not gate A weird part of javascript is trying to toggle the bits in a number. For most programming languages, like C and Java, ~ represents a bitwise NOT operation, aka one&#8217;s complement. But in javascript, ~ produces the two&#8217;s complement. Since ~num gives the two&#8217;s complement, equivalent to -(num + 1), then one would &hellip; <a href=\"https:\/\/bateru.com\/news\/2011\/03\/javascript-not-is-not-what-you-expect\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Javascript NOT is not what you expect<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11,10],"tags":[41,39,40,16],"class_list":["post-367","post","type-post","status-publish","format-standard","hentry","category-frontend-tech","category-tutorials","tag-javascript-bitwise-operations","tag-javascript-not","tag-javascript-toggle","tag-tutorial"],"_links":{"self":[{"href":"https:\/\/bateru.com\/news\/wp-json\/wp\/v2\/posts\/367","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bateru.com\/news\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bateru.com\/news\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bateru.com\/news\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bateru.com\/news\/wp-json\/wp\/v2\/comments?post=367"}],"version-history":[{"count":24,"href":"https:\/\/bateru.com\/news\/wp-json\/wp\/v2\/posts\/367\/revisions"}],"predecessor-version":[{"id":400,"href":"https:\/\/bateru.com\/news\/wp-json\/wp\/v2\/posts\/367\/revisions\/400"}],"wp:attachment":[{"href":"https:\/\/bateru.com\/news\/wp-json\/wp\/v2\/media?parent=367"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bateru.com\/news\/wp-json\/wp\/v2\/categories?post=367"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bateru.com\/news\/wp-json\/wp\/v2\/tags?post=367"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}