Bruce Garrett Cartoon
The Cartoon Gallery

A Coming Out Story
A Coming Out Story

My Photo Galleries
New and Improved!

Past Web Logs
The Story So Far archives

My Amazon.Com Wish List

My Myspace Profile

Bruce Garrett's Profile
Bruce Garrett's Facebook profile


Blogs I Read!
Alicublog

Wayne Besen

Beyond Ex-Gay
(A Survivor's Community)

Box Turtle Bulletin

Chrome Tuna

Daily Kos

Mike Daisy's Blog

The Disney Blog

Envisioning The American Dream

Eschaton

Ex-Gay Watch

Hullabaloo

Joe. My. God

Peterson Toscano

Progress City USA

Slacktivist

SLOG

Fear the wrath of Sparky!

Wil Wheaton



Gone But Not Forgotten

Howard Cruse Central

The Rittenhouse Review

Steve Gilliard's News Blog

Steve Gilliard's Blogspot Site



Great Cartoon Sites!

Tripping Over You
Tripping Over You

XKCD

Commando Cody Monthly

Scandinavia And The World

Dope Rider

The World Of Kirk Anderson

Ann Telnaes' Cartoon Site

Bors Blog

John K

Penny Arcade




Other News & Commentary

Lead Stories

Amtrak In The Heartland

Corridor Capital

Railway Age

Maryland Weather Blog

Foot's Forecast

All Facts & Opinions

Baltimore Crime

Cursor

HinesSight

Page One Q
(GLBT News)


Michelangelo Signorile

The Smirking Chimp

Talking Points Memo

Truth Wins Out

The Raw Story

Slashdot




International News & Views

BBC

NIS News Bulletin (Dutch)

Mexico Daily

The Local (Sweden)




News & Views from Germany

Spiegel Online

The Local

Deutsche Welle

Young Germany




Fun Stuff

It's not news. It's FARK

Plan 59

Pleasant Family Shopping

Discount Stores of the 60s

Retrospace

Photos of the Forgotten

Boom-Pop!

Comics With Problems

HMK Mystery Streams




Mercedes Love!

Mercedes-Benz USA

Mercedes-Benz TV

Mercedes-Benz Owners Club of America

MBCA - Greater Washington Section

BenzInsider

Mercedes-Benz Blog

BenzWorld Forum

January 5th, 2009

A Little Of What I Do For A Living

[Major Geek Alert…]

Some of you may have read the news items about Microsoft’s Zune player freezing up on its users last December 31st. The problem it turned out, was in a bit of software that calculates how many days since January 1st the current date is.  I’ve no idea why the Zune’s software needed to do that, but it isn’t important to what I’m about to show you.  I have fun doing the work I do, in a techno geeky kinda way, and I want to share a bit of that fun with you.

The code that caused that particular bug was leaked out into the wild.  Here’s the relevant fragment:

  while (days > 365)
  {
      if (IsLeapYear(year))
      {
          if (days > 366)
          {
              days -= 366;
              year += 1;
          }
      }
      else
      {
          days -= 365;
          year += 1;
      }
  }

Don’t panic…it’s just code.  Code is to a computer program what a chart is to music.  It’s not so much the program, as instructions for how to create the program.  It’s more human readable then the machine language code microprocessors digest, although that might seem a tad hard to believe if you’re seeing code here for the first time.  It’s a kind of highly structured syntax that is precise enough to describe, step-by-step, a series of actions the computer needs to perform.  That series of actions is called an ‘algorithm’.

An algorithm is a series of steps needed to perform a specific task in a specific time.  So for example, consider the steps necessary to bake a single cake.  Those steps constitute an algorithm because they perform a specific task in a specific time.  The task is baking a cake.  When the cake is baked you are done.  Note that a specific time isn’t necessarily a specific amount of time.  The important thing is there is an end to it somewhere. The steps needed for a cake factory to make ‘cakes’ is not an algorithm because there is no defined end to the task of baking cakes.  It could be one cake or many.  But you can repeat the algorithm for baking a single cake as many times as you like, once you have it defined.

Writing computer programs is essentially the art of creating well defined, simple, straightforward algorithms.  If you’ve got a head for that, the rest is a matter of mastering a particular programming language or more.  The code fragment above is in a language called C++.  Never mind why it’s called that and not something more warm and friendly like Fred or Ethel.  Computer geeks are weird like that.

This code fragment is from a larger bit of code that tries to determine the number of years the current year is from the year 1980, and the number of days since January 1st.  Never mind for now Why.  Just focus on the task: to get the number of years since 1980 and the number of days since January 1st. 

The function this code fragment lives in receives the current date in the form of the number of days since January 1, 1980.  This seems odd, but it is how computers tell time.  At the most basic level, they are merely counting fractions of seconds from a given starting point.  Consider that a mechanical wrist watch (like the one I wear) tells the time only by counting ticks.  If you know how many ticks there are in a second, then you can compute the second, the minute, and the hour by counting the number of ticks and that is just what a mechanical wrist watch does…mechanically.  Computers do pretty much the same thing electronically, but their ticks are much smaller, and far more precise.

We know there are 365 days in a normal year.  So if we get a number that’s, let’s say 10220, we might just divide that by 365 to get the number of years that have passed.  But the added factor of having leap years makes it less simple then that. 

Now let me try to make some sense of that C++ code for you.  As I said, it’s a highly structured syntax that precisely describes the steps a computer program must perform.  Just ignore the brackets…they’re just there to mark off specific sections of the code.  Don’t worry about them.

At the beginning of the code you see the word "while".  This is a Keyword in the C and C++ languages and it denotes the start of a program Loop.  A loop is a series of steps that are repeated.  They are very useful for repeating a series of steps over and over as just a few lines of code instead of one or more lines repeated exactly for every time the steps need to be executed. If, say, you had to do something a hundred times you would write the code to loop through the same steps a hundred times, rather then writing the same steps a hundred times in the code.  If the steps change, then that’s a hundred changes you need to make.  If you’ve written it as a loop you only need to change it once. 

Loops are also helpful if you don’t know ahead of time how many times you might have to repeat a particular set of steps.  In the cake baking example for instance, you might have to stir some ingredients until they are mixed properly.  If you were coding that, you’d write it as a loop where you stir the mix, and then test to see if it’s mixed well enough to stop.  If not, stir once more.  Test…stir…test…stir…  And so on until the the test says you can stop stirring now.

That test is important.  It tells you when you can stop stirring.  For now just hold this thought: it is important to have a way out of a loop.

The keyword "while" has a test enclosed in the parenthesis next to it: (days > 365).  This test compares the variable "days" against a literal value of 366.  Think of a variable as a post office box with a name on it, and something inside.  In this case, the variable is named "days" and it holds a number that represents a given number of days.  This variable is set elsewhere in the code and we don’t need to know why or how at the moment.  We’re just looking at what this one bit of code does. 

The ">" symbol is an Operator in the C and C++ languages, which means "greater then"  If "days" is "greater then" 365 then the next lines of code are executed.  This test is at the beginning of the loop, which means the condition is tested first before any of the code in the loop is executed.  If the test is true, the loop is entered.  If not, the loop is never entered.  So the loop takes a value for a number of days at its very beginning.  If that value is greater then 365, the rest of the loop executes.  If it isn’t, the loop is skipped over.  Think of it as saying "while the value stored in "days" is greater then 365, do the following…"

So we enter the body of the loop.  The next line is "if (IsLeapYear(year))"  Let me unpack that.  The word "if" is another keyword, and it denotes a logical test.  You are testing if something is, or is not true.  The part in the parenthesis is the thing you are testing.  IsLeapYear(year) is a function call with its own set of parenthesis.  Functions are bits of code that return a value.  This particular function returns a value of either true or false.  We don’t need to see how this particular works for this example…just that it will return either "true" or "false" back to our "if" test.  The word "year" in its parenthesis is another variable and it holds a number that represents the number of years since 1980. 

So we are passing in to the function IsLeapYear a number, and it returns either true or false depending on whether or not the number we give it, translates into a leap year.  Remember, we’re counting the number of years since 1980.  Lets say we make "year" equal to 3.  We could as easily write the call as "IsLeapYear(3)", and it would return false, since 1980 plus three years is 1983 which was not a leap year.

Okay…still with me?

An "if" test tests a condition, and the lines of code following the test are either executed or not depending on whether or not the test passed or failed.  If IsLeapYear(year) returns true, then the next line is executed.

The next line is another "if" test.  if (days > 366).  This test compares the variable "days" against a literal value of 366.  It is like the test at the beginning of the loop.  If "days" is "greater then" 366 then the next lines of code are executed. 

These next lines actually do something.  the line "days -= 366" means "take the value that’s stored in the variable named "days", subtract 366 from it and store the result back in that variable.  The line "year += 1" means "add one to the value stored in the variable named year and put the result back in that variable". 

A couple brackets on down (I told you to just ignore them) there is the word "else"  It is another keyword that works with the keyword "if" to denote lines of code to be executed if the if test above fails.  So in other words, if IsLeapYear(year) returns false, then the steps following the word "else" are performed.  Think of the whole thing as "if it’s a leap year do this…if it isn’t (else) do that…"  In this case, that is "subtract 365 from the value of the variable named days", and "add one to the value of the variable named year".

So…still with me?  This is what the code is doing.  The algorithm it embodies is this:

1) Repeat the following for as long as the value of "days" is greater then 365:
2) Check to see if "year" is a leap year.
3) If it is a leap year, check to see if the value of "days" is greater then 366.
4) If it is, then subtract 366 from "days" and add 1 to the value of "year"
5) If "year" isn’t a leap year, then subtract 365 from "days" and add 1 to the value of "year"

There is our loop.  Basically, it is taking a number that is the number of days since 1980, and subtracting 365 days for every normal year, 366 for every leap year, and when it finishes you should have a count of the number of years since 1980, and what’s left over is the number of days since January 1st.  Simple…no?

The bug in it is subtle.  Let’s run through it for December 31, 2007.  Lets say we have run this loop for a while and now we have a value of 26 in "year".  The value of "days" is 730. 

1) The value of "days" is greater then 365…so we do the loop again.
2) Check to see if "year" is a leap year.  26 years since 1980 is 2006.  2006 isn’t a leap year.  So the code following the "else" keyword is executed.
3) We subtract 365 from "days" and add 1 to the value of "year"
4) We’re at the beginning of our loop again.  The value of "days" is 365.  365 is not greater then 365.  So the condition for continuing the loop is now false.  So now we can exit the loop.
5) The end values are, year = 27, days = 365.

Okay.  That works.  But now let’s try it for December 31, 2008.  Lets say we have run this loop for a while and now we have a value of 27 in "year".  The value of "days" is 731.

1) The value of "days" is greater then 365…so we do the loop again.
2) Check to see if "year" is a leap year.  27 years since 1980 is 2007.  2007 isn’t a leap year.  So the code following the "else" keyword is executed.
3) We subtract 365 from "days" and add 1 to the value of "year"
4) We’re at the beginning of our loop again.  The value of "days" is 366.  366 is greater then 365.  So the condition for continuing the loop is still true.
5) Check to see if "year" is a leap year.  2008 is a leap year.  So the code following the "if" keyword is executed.
6) Check to see if the value of "days" is greater then 366.  366 isn’t greater then 366, it’s equal to 366…so the code following the "if" keyword is not executed.
7) We’re at the beginning of our loop again.  The value of "days" is still 366 and the value of year is still 28.  366 is greater then 365.  So the condition for continuing the loop is still true.
10) Check to see if "year" is a leap year.  The value of year wasn’t changed by the last run through the loop.  It is still 2008 and 2008 isn’t a leap year.  So the code following the "if" keyword is executed.

(can you see this thing starting to run away now…?)

11)  Check to see if the value of "days" is greater then 366.  366 isn’t greater then 366, it’s equal to 366…so the code following the "if" keyword is not executed.
12) We’re at the beginning of the loop again…

And that’s where we will keep on ending up until the heat death of the universe, or the Zune’s battery dies, whichever comes first.  This is why the Zunes all locked up on December 31st, 2008.  The code works fine during a normal year, and on every day but the last day of a leap year.  But on the last day of a leap year that loop will run indefinitely, because there is no way out of it on that one day.

Since this code was leaked out into the wild, everybody who does this for a living has an opinion on how to write that algorithm better.  There is a kind of fine art and a pure pleasure to some of us in crafting tight, simple, elegant algorithms and some folks have their own deeply held religious beliefs on how to do it best.  I haven’t had time to really wrap my head around what this algorithm is doing, but for kicks and grins I might try to write a better version of it myself later.  It’s kinda fun to take something like this and try to craft something simple and clean and so logically pure it’s beautiful just to look at.  But I’m in a testing and deployment phase of the project I’m one at work now though, and what went through my head when I saw this was they obviously didn’t test how it behaved during a leap year.

This is the world I live and work in.  This is what programming is and what programmer’s do.  We build these tight little algorithms and embody them in computer code that hopefully allows you to get things done.  Except when they don’t.

[Edited a tad to explain the test at the start of the loop, and make some of the rest of it clearer…]

Leave a Reply

Visit The Woodward Class of '72 Reunion Website For Fun And Memories, WoodwardClassOf72.com


What I'm Currently Reading...




What I'm Currently Watching...




What I'm Currently Listening To...




Comic Book I've Read Recently...



web
stats

This page and all original content copyright © 2024 by Bruce Garrett. All rights reserved. Send questions, comments and hysterical outbursts to: bruce@brucegarrett.com

This blog is powered by WordPress and is hosted at Winters Web Works, who also did some custom design work (Thanks!). Some embedded content was created with the help of The Gimp. I proof with Google Chrome on either Windows, Linux or MacOS depending on which machine I happen to be running at the time.