{"id":36593,"date":"2005-01-26T07:00:00","date_gmt":"2005-01-26T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2005\/01\/26\/the-strangest-way-of-rounding-down-to-the-nearest-quarter\/"},"modified":"2005-01-26T07:00:00","modified_gmt":"2005-01-26T07:00:00","slug":"the-strangest-way-of-rounding-down-to-the-nearest-quarter","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20050126-00\/?p=36593","title":{"rendered":"The strangest way of rounding down to the nearest quarter"},"content":{"rendered":"<p>\nIn a previous life, I wrote database software.\nA customer complained that one of their reports was taking an\nunacceptably long amount of time to generate, and I was asked\nto take a look at it even though it wasn&#8217;t my account.\n<\/p>\n<p>\nThe report was a vacation-days report, listing the number of\nvacation days taken and available for each employee.  Vacation\ndays accrued at a fixed rate but were granted only in\nquarter-day increments. For example, if you earned 15 vacation\ndays per year and the year was 32% complete, then you had\naccrued 32% &times; 15 = 4.8 vacation days, of which 4.75 were\navailable to use.\n<\/p>\n<p>\nThe existing code to round the number of accrued days down to\nthe nearest quarter-day went something like this:\n<\/p>\n<pre>\n* assume that at this point, ACCRUED is the number\n* of accrued days.\nPRIVATE S,F\n* STR(ACCRUED,6,2) converts ACCRUED to a 6-character\n* string: 3 integer digits, a decimal point, and two\n* fractional digits.  Excess fractional digits are rounded.\nSTORE STR(ACCRUED,6,2) TO S\nSTORE RIGHT(S,2) TO F        &amp;&amp; extract digits after decimal\nIF F &lt; &quot;25&quot;\n F = &quot;00&quot;                    &amp;&amp; 00 to 24 becomes 00\nELSE\n IF F &lt; &quot;50&quot;\n  F = &quot;25&quot;                   &amp;&amp; 25 to 49 becomes 25\n ELSE\n  IF F &lt; &quot;75&quot;\n   F = &quot;50&quot;                  &amp;&amp; 50 to 74 becomes 50\n  ELSE\n   F = &quot;75&quot;                  &amp;&amp; 75 to 99 becomes 75\n  ENDIF\n ENDIF\nENDIF\nROUNDED = VAL(LEFT(S,4) + F) &amp;&amp; reconstruct value and convert\n<\/pre>\n<p>\nIn other words, the code converted the number to a string,\nextracted the digits after the decimal point, did string comparisons\nto figure out which quartile the fraction resided in, then\ncreated a new string with the replacement fraction and converted\nthat string back to a number.\nAnd all this in an interpreted language.\n<\/p>\n<p>\nThis code fragment was repeated each time rounding-down was\nneeded because the language supported only 32 subroutines,\nand this procedure wasn&#8217;t important enough to be worth kicking\nout one of the other existing subroutines.\n<\/p>\n<p>\nI replaced this seventeen-line monstrosity with the one-line\nequivalent each time it occurred, and the report ran much faster.\n<\/p>\n<p>\n(This is nowhere near the strangest way of implementing rounding.\n<a HREF=\"http:\/\/thedailywtf.com\/archive\/2004\/09\/14\/1774.aspx\">\nThere are far worse examples<\/a>.)\n<\/p>\n<p>\n<strong>Exercise<\/strong>: What is the one-line equivalent?\n<\/p>\n<p>\n<strong>Exercise<\/strong>: What is the double-rounding bug in the original\ncode?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In a previous life, I wrote database software. A customer complained that one of their reports was taking an unacceptably long amount of time to generate, and I was asked to take a look at it even though it wasn&#8217;t my account. The report was a vacation-days report, listing the number of vacation days taken [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[26],"class_list":["post-36593","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>In a previous life, I wrote database software. A customer complained that one of their reports was taking an unacceptably long amount of time to generate, and I was asked to take a look at it even though it wasn&#8217;t my account. The report was a vacation-days report, listing the number of vacation days taken [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/36593","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=36593"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/36593\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=36593"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=36593"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=36593"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}