{"id":16254,"date":"2020-02-08T17:08:20","date_gmt":"2020-02-08T17:08:20","guid":{"rendered":"https:\/\/www.bartbusschots.ie\/s\/?p=16254"},"modified":"2020-02-13T17:43:32","modified_gmt":"2020-02-13T17:43:32","slug":"pbs-tidbit-1-of-y-display-values-are-not-data","status":"publish","type":"post","link":"https:\/\/www.bartbusschots.ie\/s\/2020\/02\/08\/pbs-tidbit-1-of-y-display-values-are-not-data\/","title":{"rendered":"PBS Tidbit 1 of Y \u00e2\u20ac\u201d Display Values are not Data!"},"content":{"rendered":"<p>Listener <a href=\"https:\/\/twitter.com\/lbutlr\/\" rel=\"noopener noreferrer\" target=\"_blank\">@lbutlr<\/a> pointed out <a href=\"https:\/\/twitter.com\/lbutlr\/status\/1221867924589121536\" target=\"_blank\" rel=\"noopener noreferrer\">on Twitter<\/a> that the sample solution to the challenge set in <a href=\"https:\/\/bartificer.net\/pbs88\" rel=\"noopener noreferrer\" target=\"_blank\">PBS 88<\/a> as I originally posted it in <a href=\"https:\/\/bartificer.net\/pbs89\" rel=\"noopener noreferrer\" target=\"_blank\">PBS 89<\/a> had a bug \u00e2\u20ac\u201d it sometimes got its maths spectacularly wrong!<\/p>\n<p style=\"text-align: center\"><img decoding=\"async\" src=\"https:\/\/www.bartbusschots.ie\/s\/wp-content\/uploads\/2020\/02\/image.jpg\" alt=\"PBS 88 Solution Bug\" width=\"480\" class=\"alignnone size-full wp-image-16255\" style=\"border: 1px solid black\" srcset=\"https:\/\/www.bartbusschots.ie\/s\/wp-content\/uploads\/2020\/02\/image.jpg 782w, https:\/\/www.bartbusschots.ie\/s\/wp-content\/uploads\/2020\/02\/image-300x166.jpg 300w, https:\/\/www.bartbusschots.ie\/s\/wp-content\/uploads\/2020\/02\/image-768x425.jpg 768w\" sizes=\"(max-width: 782px) 100vw, 782px\" \/><\/p>\n<p>It&#8217;s important to note that the bug did not affect all currencies, just some currencies.<\/p>\n<p>The line of code for doing the currency conversion is supremely simple:<\/p>\n<pre class=\"lang:js decode:true \" >const convAmount = baseAmount * rate;<\/pre>\n<p>How on earth can there be a bug that is something so simple that only manifests for some currencies but not for others?<\/p>\n<p><!--more--><\/p>\n<div class=\"podcast\">\n<p>Listen Along: <a href=\"https:\/\/www.podfeet.com\/blog\/2020\/02\/pbs-tb-1\/\" target=\"_blank\" rel=\"noopener noreferrer\">PBS Tidbit 1 of Y \u00e2\u20ac\u201d Display Values are not Data!<\/a><\/p>\n<!--[if lt IE 9]><script>document.createElement('audio');<\/script><![endif]-->\n<audio class=\"wp-audio-shortcode\" id=\"audio-16254-1\" preload=\"none\" style=\"width: 100%;\" controls=\"controls\"><source type=\"audio\/mpeg\" src=\"https:\/\/media.blubrry.com\/nosillacast\/traffic.libsyn.com\/nosillacast\/CCATP_2020_02_08-TB1.mp3.mp3?_=1\" \/><a href=\"https:\/\/media.blubrry.com\/nosillacast\/traffic.libsyn.com\/nosillacast\/CCATP_2020_02_08-TB1.mp3.mp3\">https:\/\/media.blubrry.com\/nosillacast\/traffic.libsyn.com\/nosillacast\/CCATP_2020_02_08-TB1.mp3.mp3<\/a><\/audio><\/div>\n<h2>Diagnosing the Problem<\/h2>\n<p>The first thing I noticed was that the bug affected low-value currencies. When each unit of the currency has a low value then the exchange rates will involve small numbers. Maybe the combination of a big base amount and a tiny exchange rate was exceeding the amount of precision a JavaScript number can store?<\/p>\n<p>Javascript numbers are 64bit numbers (<em>double-precision<\/em> numbers or simply <em>doubles<\/em> in programming jargon), so they can only capture so much detail \u00e2\u20ac\u201d as a science student I ran into the limit of doubles when doing homework assignments, so I knew it was at least conceivable. Looking more closely that didn&#8217;t make sense \u00e2\u20ac\u201d the numbers were not big enough, and the rates not small enough for that to be a reasonable explanation.<\/p>\n<p>I was on the right track though \u00e2\u20ac\u201d it was a precision problem, but not with JavaScript&#8217;s number storage, but with my code!<\/p>\n<p>As explained in the description of the solution in <a href=\"https:\/\/bartificer.net\/pbs89\" rel=\"noopener noreferrer\" target=\"_blank\">PBS 89<\/a>, I used data attributes to store the rate within the relevant row of the card using HTML data attributes. Without thinking about it the value I stored in the data attribute was the rate as displayed to the user \u00e2\u20ac\u201d <code>rounded to 2 decimal places<\/code>!<\/p>\n<p>The data attribute is added into the currency&#8217;s item within this part of my Mustache template:<\/p>\n<pre class=\"lang:xhtml decode:true \" >\r\n&lt;li class=\"list-group-item currencyRate\" data-currency=\"{{{code}}}\" data-rate=\"{{{rate}}}\"&gt;\r\n<\/pre>\n<p>And the rate is added into the view with this line:<\/p>\n<pre class=\"lang:js mark:4 decode:true \" >\r\ncardView.rates.push({\r\n  code: cc,\r\n  rate: numeral(curData.rates[cc]).format('0,0[.]00'),\r\n  ...CURRENCIES[cc]\r\n});\r\n<\/pre>\n<p>And there we have it \u00e2\u20ac\u201d the view was originally written purely to present information to the user, and I then re-used that view to inject data into the DOM elements. This is a great illustration of why you want to avoid passing information formatted for consumption by humans into computations!<\/p>\n<p>Bottom line \u00e2\u20ac\u201d as I suspected, it was indeed a loss of precision,  but one of my own making \u00e2\u20ac\u201d oops!<\/p>\n<p>There is a silver lining though, I have the power to fix problems I created \u00f0\u0178\u2122\u201a<\/p>\n<h2>Fixing the Bug<\/h2>\n<p>The solution is fundamentally very simple \u00e2\u20ac\u201d add the true rate into view as well as the formatted rate, then use that true rate to populate the data attribute.<\/p>\n<p>The first step was to tweak the code that creates the view to add a new key named <code>rawRate<\/code>:<\/p>\n<pre class=\"lang:js mark:4 decode:true \" >\r\ncardView.rates.push({\r\n  code: cc,\r\n  rate: numeral(curData.rates[cc]).format('0,0[.]00'),\r\n  rawRate: curData.rates[cc],\r\n  ...CURRENCIES[cc]\r\n});\r\n<\/pre>\n<p>The template could then be updated to use the raw rate:<\/p>\n<pre class=\"lang:xhtml decode:true \" >\r\n&lt;li class=\"list-group-item currencyRate\" data-currency=\"{{{code}}}\" data-rate=\"{{{rawRate}}}\"&gt;\r\n<\/pre>\n<p>Much better!<\/p>\n<p style=\"text-align: center\">\n<img decoding=\"async\" src=\"https:\/\/www.bartbusschots.ie\/s\/wp-content\/uploads\/2020\/02\/Screenshot-2020-02-08-at-16.55.38.png\" alt=\"PBS 88 Bug Fixed\" width=\"480\" class=\"alignnone size-full wp-image-16258\" style=\"border: 1px solid black\" srcset=\"https:\/\/www.bartbusschots.ie\/s\/wp-content\/uploads\/2020\/02\/Screenshot-2020-02-08-at-16.55.38.png 1370w, https:\/\/www.bartbusschots.ie\/s\/wp-content\/uploads\/2020\/02\/Screenshot-2020-02-08-at-16.55.38-300x242.png 300w, https:\/\/www.bartbusschots.ie\/s\/wp-content\/uploads\/2020\/02\/Screenshot-2020-02-08-at-16.55.38-1024x827.png 1024w, https:\/\/www.bartbusschots.ie\/s\/wp-content\/uploads\/2020\/02\/Screenshot-2020-02-08-at-16.55.38-768x620.png 768w\" sizes=\"(max-width: 1370px) 100vw, 1370px\" \/><\/p>\n<p>You&#8217;ll find <a href=\"https:\/\/github.com\/bartificer\/programming-by-stealth\/blob\/master\/instalmentResources\/pbs89\/pbs88-challengeSolution\/index.html\" rel=\"noopener noreferrer\" target=\"_blank\">the full code for the challenge solution on GitHub<\/a>.<\/p>\n<h2>Related Content<\/h2>\n<ul>\n<li><a href=\"https:\/\/www.podfeet.com\/blog\/2020\/02\/pbs-tb-1\/\" rel=\"noopener noreferrer\" target=\"_blank\">The episode of Chit Chat Across the Pond Podcast for the 8th of February 2020<\/a> which is based in this post.<\/li>\n<li><a href=\"https:\/\/www.podfeet.com\/blog\/2020\/02\/when-currency-rate-decimals-go-wrong\/\" rel=\"noopener noreferrer\" target=\"_blank\">A blog post from Allison Sheridan<\/a> explaining how she enhanced her sample solution to the same challenge to deal with currencies with different numbers of decimal places.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Listener @lbutlr pointed out on Twitter that the sample solution to the challenge set in PBS 88 as I originally posted it in PBS 89 had a bug \u00e2\u20ac\u201d it sometimes got its maths spectacularly wrong! It&#8217;s important to note that the bug did not affect all currencies, just some currencies. The line of code [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[12,16],"tags":[420,582,458],"series":[],"class_list":["post-16254","post","type-post","status-publish","format-standard","hentry","category-computers-tech","category-programming","tag-javascript","tag-programming-by-stealth-tidbit","tag-tutorial"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p7t9xK-4ea","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/posts\/16254","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/comments?post=16254"}],"version-history":[{"count":11,"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/posts\/16254\/revisions"}],"predecessor-version":[{"id":16292,"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/posts\/16254\/revisions\/16292"}],"wp:attachment":[{"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/media?parent=16254"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/categories?post=16254"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/tags?post=16254"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/www.bartbusschots.ie\/s\/wp-json\/wp\/v2\/series?post=16254"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}