{"id":553,"date":"2011-04-07T22:59:18","date_gmt":"2011-04-08T04:59:18","guid":{"rendered":"http:\/\/bateru.com\/news\/?p=553"},"modified":"2014-11-15T23:38:17","modified_gmt":"2014-11-16T05:38:17","slug":"code-of-the-day-javascript-significant-figures","status":"publish","type":"post","link":"https:\/\/bateru.com\/news\/2011\/04\/code-of-the-day-javascript-significant-figures\/","title":{"rendered":"Code of the Day: Javascript Significant Figures"},"content":{"rendered":"<p>Did you know that JavaScript automatically trims off trailing zeros on numbers with decimals?<br \/>\nWell now you do, and in order to save precision you must wrap the number inside a string.<br \/>\nExample: <\/p>\n<pre lang='javascript' line='1'>\r\nvar a = \"0.0100\";\r\nvar b = 0.0100;                           \/\/ To save space the interpreter cuts off the last two zeros.\r\nconsole.log( a === b.toString() );\t\/\/ displays false because a = \"0.0100\" and b = 0.01\r\n\r\nconsole.log( 1000 === 1000.000 );\t\/\/ displays true\r\nconsole.log( 0.1 === 0.1000 );\t\t\/\/ displays true\r\n<\/pre>\n<p>Some might argue that you can use <a href=\"http:\/\/www.w3schools.com\/jsref\/jsref_toprecision.asp\">num.toPrecision()<\/a> to save the trailing zeros. But what most are unaware of is that toPrecision() returns a <b>string<\/b>.<\/p>\n<pre lang='javascript' line=\"1\">\r\nvar num = (120.0).toPrecision(8);\r\nconsole.log( num );                      \/\/ displays 120.00000\r\nconsole.log( typeof num );            \/\/ displays string\r\nconsole.log( +num );                    \/\/ displays 120\r\n\/\/ +num is a shortcut for parseInt( num, 10);\r\n<\/pre>\n<p>\nNow let&#8217;s see what happens with leading zero&#8217;s.<\/p>\n<pre lang='javascript' line='1'>\r\n\/\/A leading 0 in front of a number converts it base 8.\r\n\/\/ a.k.a. parseInt( num, 8);\r\nconsole.log(0011);\t\t\/\/ Displays 9\r\nconsole.log( 010.1000 );\t\t\/\/ Error! Octals can only be whole numbers.\r\nconsole.log( 00000.1000 );\t\/\/ Error for the same reason.\r\n\/\/ The problem is that a leading zero will cause the number to be converted to octal.\r\n\/\/ Thus, an error is generated because the decimal point is neither an operation nor semicolon.\r\n<\/pre>\n<p>Using numbers as strings can be useful when trying to find the Significant Digits, like in the following function.<\/p>\n<pre lang='javascript' line='1'>\r\n\/\/ Returns the significant digits of a number.\r\n\/\/ @param {Number|String} num\r\n\/\/ @return Returns -1 if invalid input, otherwise will return a positive number.\r\nvar getSigFigs = function (num) {\r\n  if (!isFinite(Number(num))) {\r\n    return -1;\r\n  }\r\n  var n = String(num).trim(),\r\n  FIND_FRONT_ZEROS_SIGN_DOT_EXP = \/^[\\D0]+|\\.|([e][^e]+)$\/g,\r\n  FIND_RIGHT_ZEROS = \/0+$\/g;\r\n  \r\n  if (!\/\\.\/.test(num)) {\r\n    n = n.replace(FIND_RIGHT_ZEROS, \"\");\r\n  }\r\n  return n.replace(FIND_FRONT_ZEROS_SIGN_DOT_EXP, \"\").length;\r\n};\r\n<\/pre>\n<p><b>Usage<\/b>:<\/p>\n<pre lang='javascript' line=\"1\">\r\nconsole.log( getSigFigFromNum( \"0.01230\" ) == 5);\r\n<\/pre>\n<h2>Test cases<\/h2>\n<pre lang='javascript' line='1'>\r\n\r\n\/\/ Try using Qunit to run tests.\r\nvar assert = {};\r\nassert.equal = function (a, b) {\r\n  if (a != b) {\r\n    console.error(\"FAIL: --> %s != %s\", a, b);\r\n  } else {\r\n    console.log(\"Pass: %s == %s\", a, b);\r\n  }\r\n};\r\nvar test = function (name, fn) {\r\n  console.log(\"\\n#Testing: %s\", name);\r\n  fn();\r\n};\r\ntest(\"Invalid numbers\", function () {\r\n  assert.equal(getSigFigs(\"742400g\"), -1);\r\n  assert.equal(getSigFigs(\"g742400\"), -1);\r\n  assert.equal(getSigFigs(\"Infinity\"), -1);\r\n  assert.equal(getSigFigs(\"-Infinity\"), -1);\r\n  assert.equal(getSigFigs(\"NaN\"), -1);\r\n});\r\nvar testWithPrefixes = function (prefixes, nums, fn) {\r\n  prefixes.forEach(function (prefix) {\r\n    nums.forEach(function (num) {\r\n      \/\/assert.equal( \"Testing \" + expected + \"\" prefix+expected, fn(prefix+num));\r\n    });\r\n  });\r\n};\r\ntest(\"Whole Numbers\", function () {\r\n  assert.equal(getSigFigs(\"742400\"), 4);\r\n  assert.equal(getSigFigs(\"742000\"), 3);\r\n  assert.equal(getSigFigs(\"740000\"), 2);\r\n  assert.equal(getSigFigs(\"700000\"), 1);\r\n});\r\ntest(\"Negative Whole Numbers\", function () {\r\n  assert.equal(getSigFigs(\"-742400\"), 4);\r\n  assert.equal(getSigFigs(\"-742000\"), 3);\r\n  assert.equal(getSigFigs(\"-740000\"), 2);\r\n  assert.equal(getSigFigs(\"-700000\"), 1);\r\n});\r\ntest(\"+Whole numbers\", function () {\r\n  assert.equal(getSigFigs(\"+742400\"), 4);\r\n  assert.equal(getSigFigs(\"+742000\"), 3);\r\n  assert.equal(getSigFigs(\"+740000\"), 2);\r\n  assert.equal(getSigFigs(\"+700000\"), 1);\r\n});\r\ntest(\"Decimals\", function () {\r\n  assert.equal(getSigFigs(\"0.07284\"), 4);\r\n  assert.equal(getSigFigs(\"0.0728\"), 3);\r\n  assert.equal(getSigFigs(\"0.072\"), 2);\r\n  assert.equal(getSigFigs(\"0.07\"), 1);\r\n  assert.equal(getSigFigs(\"123.07\"), 5);\r\n});\r\ntest(\"Negative Decimals\", function () {\r\n  assert.equal(getSigFigs(\"-0.07284\"), 4);\r\n  assert.equal(getSigFigs(\"-0.0728\"), 3);\r\n  assert.equal(getSigFigs(\"-0.072\"), 2);\r\n  assert.equal(getSigFigs(\"-0.07\"), 1);\r\n  assert.equal(getSigFigs(\"-10.07\"), 4);\r\n});\r\ntest(\"Decimals\", function () {\r\n  assert.equal(getSigFigs(\"+0.07284\"), 4);\r\n  assert.equal(getSigFigs(\"+0.0728\"), 3);\r\n  assert.equal(getSigFigs(\"+0.072\"), 2);\r\n  assert.equal(getSigFigs(\"+0.07\"), 1);\r\n});\r\ntest(\"Zero\", function () {\r\n  assert.equal(getSigFigs(\"0.0\"), 0);\r\n  assert.equal(getSigFigs(\"-0.0\"), 0);\r\n  assert.equal(getSigFigs(\"0\"), 0);\r\n  assert.equal(getSigFigs(\"+0\"), 0);\r\n  assert.equal(getSigFigs(\"-0\"), 0);\r\n});\r\n\r\ntest(\"E notated\", function () {\r\n  assert.equal(getSigFigs(\"1.3e32\"), 2);\r\n  assert.equal(getSigFigs(\"-1.23e-32\"), 3);\r\n  assert.equal(getSigFigs(\"-1.023e+120\"), 4);\r\n  assert.equal(getSigFigs(\"+5.023e+32\"), 4);\r\n  assert.equal(getSigFigs(\"+5.0230e+32\"), 5);\r\n});\r\n<\/pre>\n<p>Can you think of any other useful examples for number wrapped in strings?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Did you know that JavaScript automatically trims off trailing zeros on numbers with decimals? Well now you do, and in order to save precision you must wrap the number inside a string. Example: var a = &#8220;0.0100&#8221;; var b = 0.0100; \/\/ To save space the interpreter cuts off the last two zeros. console.log( a &hellip; <a href=\"https:\/\/bateru.com\/news\/2011\/04\/code-of-the-day-javascript-significant-figures\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Code of the Day: Javascript Significant Figures<\/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,12,10],"tags":[164],"class_list":["post-553","post","type-post","status-publish","format-standard","hentry","category-frontend-tech","category-science","category-tutorials","tag-javascript"],"_links":{"self":[{"href":"https:\/\/bateru.com\/news\/wp-json\/wp\/v2\/posts\/553","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=553"}],"version-history":[{"count":23,"href":"https:\/\/bateru.com\/news\/wp-json\/wp\/v2\/posts\/553\/revisions"}],"predecessor-version":[{"id":1281,"href":"https:\/\/bateru.com\/news\/wp-json\/wp\/v2\/posts\/553\/revisions\/1281"}],"wp:attachment":[{"href":"https:\/\/bateru.com\/news\/wp-json\/wp\/v2\/media?parent=553"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bateru.com\/news\/wp-json\/wp\/v2\/categories?post=553"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bateru.com\/news\/wp-json\/wp\/v2\/tags?post=553"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}