Learn to Code
John F. Dumas
contact me | resume | how it works | example programs | testimonials | main page

Help Example: One

one | two | three | four | five


► QUESTION: I'm having trouble with this javascript program, it is supposed to report back the number of even digits in a given number but it doesn't appear to be working. Here's a summary of the results I am getting along with the correct results:

   Number   countEvenDigits   correct answer
   ======   ===============   ==============
    0        1                 1
    1        0                 0
    2        1                 1
    22       1                 2  [X]
    222      1                 3  [X]
    333      0                 0
    404      1                 3  [X]
    440      2                 3  [X]
    44       1                 2  [X]
    7        0                 0

Here is my 'countEvenDigits' function, can you help me figure out what might be going wrong?

   function countEvenDigits(value)
   {
      var number = value;
      var count  = 0;

      if(number == 0)
         count++;

      while(number > 0)
      {
         var digit = number % 10;

         if(digit % 2 == 0)
            count++;

         number /= 10;
      }

      return(count);
   }


► ANSWER: Certainly! I already have an pretty good idea already what the problem is but let's take a closer took to be sure. Consider this line:

      number /= 10;

Suppose the value of 'number' currently is 333, what would its value be after executing the line above? Intuition says that answer ought to be 33 but let's add an 'alert' to the code and see what transpires. Here's the change made to 'countEvenDigits':

   function countEvenDigits(value)
   {
      var number = value;
      var count  = 0;

      if(number == 0)
         count++;

      while(number > 0)
      {
         var digit = number % 10;

         if(digit % 2 == 0)
            count++;

         var before = "Number: " + number;

         number /= 10;

         var after = "Number: " + number;

         alert(before + ", " + after);
      }

      return(count);
   }

Also, your original program used a button to call your 'test' function, in order to leave that functionality in place (while investigating this issue) we create a second function 'test2':

   function test2()
   {
      countEvenDigits(333);
   }

And lastly, change the call from 'test' to 'test2' in your button's onClick value:

  <form>
   <input type="button" value="Test countEvenDigits" onClick="test2()">
  </form>

Note that at this point, we can now thoroughly exercise 'countEvenDigits' very easily while also hanging on to our original testing code (which can be trivially reactivated by having our button call 'test()' again instead of 'test2()'. When the program is executed, we see:

   Number: 333,                 Number: 33.3
   Number: 33.3,                Number: 3.299999999
   Number: 3.299999999,         Number: .3329999999
   Number: .3329999999,         Number: .0332999999
   ...

   etc.

As you can see, we're actually fortunate here not to be stuck in an infinite loop! With most programming languages, dividing one integer by another yields an integer but javascript is different. By default, all division is done with real numbers which is why this code:


         if(digit % 2 == 0)
            count++;

Doesn't end up being executed as often as we thought it might. As it turns out though, the solution for this is pretty straightforward. Javascript provides: 'Math.floor' which rounds its argument downwards to the nearest integer and returns the result. Applying just that change:

   function countEvenDigits(value)
   {
      var number = value;
      var count  = 0;

      if(number == 0)
         count++;

      while(number > 0)
      {
         var digit = number % 10;

         if(digit % 2 == 0)
            count++;

         var output = "Number: " + number;

         number = Math.floor(number / 10);
            
         output += " -> " + number;

         alert(output);
      }

      return(count);
   }

now produces results that are in line with our expectations:

      Number: 333, Number: 33
      Number: 33,  Number: 3
      Number: 3,   Number: 0

Removing the 'alert' from 'countEvenDigits' and then changing our button's 'onClick' callback to be 'test()' again (not test2, the function we used to debug this problem) now yields the expected results:

   Number   countEvenDigits   correct answer
   ======   ===============   ==============
    0        1                 1
    1        0                 0
    2        1                 1
    22       2                 2
    222      3                 3
    333      0                 0
    404      3                 3
    440      3                 3
    44       2                 2
    7        0                 0

Wrapping up, even though we no longer are calling 'test2()' anywhere in our code should we now remove it? It's open to debate, but I would argue it does little harm to leave it in there and does provide a "hook" for some subsequent programmer to be able to work on this code in a non-intrusive fashion.

If we found it helpful/useful to be able to route around the main body of the code for specific reasons/testing it's a good bet those that follow us will too.


Reference Files


© John F. Dumas | johnfdumas@gmail.com | main page | top of page