3

What am I missing here? This script looks right to me.

But for some reason when I send it a zipcode of 02897 (or anything that should be Rhode Island), it returns New Hampshire. Aside from political beliefs Javascript developers may have (sure most people would prefer to live in New Hampsire than Rhode Island), why doesn't this script work?

New Jersey and Alabama work fine. Why can't Rhode Island get some love?

function getState(zip) {
    var thiszip = zip; // parseInt(zip);
    if (thiszip >= 35000 && thiszip <= 36999) {
            thisst = 'AL';
            thisstate = "Alabama";
            }
    else if (thiszip >= 03000 && thiszip <= 03899) {
        thisst = 'NH';
        thisstate = "New Hampshire";
        }
    else if (thiszip >= 07000 && thiszip <= 08999) {
        thisst = 'NJ';
        thisstate = "New Jersey";
        } 
    else if (thiszip >= 02800 && thiszip <= 02999) {
        thisst = 'RI';
        thisstate = "Rhode Island";
        }
    else {
        thisst = 'none';
    }
   return thisst;
}
Tony Brasunas
  • 4,012
  • 3
  • 39
  • 51

2 Answers2

9

03000 equals 1536 as a decimal.

This is because the leading zero causes the value to be interpreted as an octal.

Since in the end you are doing number value comparisons, why not omit the leading zero in your comparison?

else if (thiszip >= 3000 && thiszip <= 3899) {

otherwise, use parseInt and declare decimal:

else if (thiszip >= parseInt(03000, 10) && thiszip <= parseInt(03899, 10)) {
                                 // ^^^ pass radix parameter          ^^^ pass radix parameter

And you probably want to parseInt the value being passed in:

var thiszip = parseInt(zip, 10);

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt

Kevin Boucher
  • 16,426
  • 3
  • 48
  • 55
  • Wow, I knew it had to be something strange like this. Defaulting to octal values in javascript. Love it. Thank you for your quick answer. Now, you have three instructions to fix it, in this form: do A or B and C. Can you add parentheses? Is it, do A or (B and C) or is it, do (A or B) and C? – Tony Brasunas Aug 07 '15 at 16:07
  • I know it's been a long time, but this isn't working for me in Chrome. I find that `parseInt(00300, 10)` returns 192. Even `Number(00300)` returns 192. – Tony Brasunas Mar 27 '18 at 22:04
  • @TonyBrasunas The value passed to `parseInt` would need to be a string: `parseInt("00300", 10)`. However, you cannot do this: `parseInt(00300.toString(), 10)` because the octal will be calclulated first and your string would thus be _192_. I'm not sure if this has always been the case, or the engine has changed. – Kevin Boucher Apr 19 '18 at 17:41
  • So how do you handle an incoming parameter that is not a string yet? – Tony Brasunas Apr 20 '18 at 21:04
  • In fact I can't find any way to deal with a number passed in with a leading zero. Strange but if **zip** is `00300` there is no way to properly evaluate the function. – Tony Brasunas Apr 20 '18 at 21:22
  • 1
    @TonyBrasunas I think this will do what you want: `00300.toString(8)` (Yields "300".) – Kevin Boucher Apr 23 '18 at 17:22
  • 1
    wow, great discovery. So you can pass in a `radix` to `toString()` as you do into `parseInt()`. This might be enough for me to replace the error I otherwise throw if a non-string is passed into the function. – Tony Brasunas Apr 25 '18 at 00:32
4

If a number starts with zero in javascript it can be treated as octal.

Quote from the following docs...

If the input string begins with "0", radix is eight (octal) or 10 (decimal). Exactly which radix is chosen is implementation-dependent. ECMAScript 5 specifies that 10 (decimal) is used, but not all browsers support this yet. For this reason always specify a radix when using parseInt.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt

However that's not the only thing at play here. If you were only comparing octals cast as decimals you would get the output you expect. In chrome 43 passing in a number that cannot be converted to octals (any digit has an 8 or 9) will keep it as a base 10.

That is probably why if statements before Rhode Island gave you the output you expected. For Example you might have passed in a zip of 03274 expecting New Hampshire and you would get what you expect. The if statement is actually doing this...

03274 >= 03000 && 03274 <= 03899

converts to...

1724 >= 1536 && 1724 <= 3899

However when you pass in 02897 expecting Rhode Island the logic is going to evaluate to True on the New Hampshire if statement. Here's what the actual comparison is...

02897 >= 03000 & 02897 <= 03899

converts to....

2897 >= 1536 && 2897 <= 3899

See Kevin's answers for how to actually fix the function to work as intended.

Tony Brasunas
  • 4,012
  • 3
  • 39
  • 51
abaldwin99
  • 903
  • 1
  • 8
  • 26
  • I commented that JS will ignore the 0 which could well be wrong, actually. I assumed JavaScript would interpret this as a number but I think there's a saying about assumptions! – DylanB Aug 07 '15 at 01:06
  • It is a combination of both issues. If you `console.log` 02897 you get 2897 if you log 03000 you get 1536. – abaldwin99 Aug 07 '15 at 01:10
  • 1
    well it IS interpreted as a number but not as a decimal, but an octal, and that's the greatest problem when handling postal/zip codes. – My1 Nov 13 '15 at 10:43