Seems perfectly fine behaviour to me. You're not comparing a "number", you're comparing the string "5". The string "5" is equal to the upper-case version of the string "5", so it is an upper-case string. The same goes for lower.

This behaviour is necessary since you may be testing:

if (X5 isupper) echo -a TRUE

Obviously the 5 will be ignored in both strings-- except in your string there's nothing else to compare. Therefore you can't check that the string is all upper-case, you must check that an upper-case string has no lower-case characters. Since the string "5" has no lower-case characters, it is considered upper-case. It also has no upper-case characters, so it is also lower-case. You can consider this "undefined", if you'd like. It's not wrong.

As a sidenote, this is what you'd expect in any programming language:

strtoupper("5") == "5" // true
strtolower("5") == "5" // true

toupper('5') == '5' // true
tolower('5') == '5' // true

"5".toUpperCase() == "5" // true
"5".toLowerCase() == "5" // true

And finally mIRC (this is basically what mIRC is doing):
$upper(5) == 5 ; true
$lower(5) == 5 ; true

Again, it should be clear: isupper/islower are for string comparison here, not number comparison (there is no number comparison for isupper/lower). String comparison checks that the bytes given are equal-- in the case of isupper, that the bytes given ("5") is equal to bytes of the upper case version of that string.. indeed, they are the same set of bytes, and the same goes for lower-case.

- argv[0] on EFnet #mIRC
- "Life is a pointer to an integer without a cast"