Javascript Checking for NaN - Results not as expected - javascript

I have an application that reads in a number via ajax, the number is hexadecimal and I parse it and convert to decimal.
The numbers come in through a wireless serial link and are not 100% reliable so I need to check them before I start processing the data. The numbers take the form ****025781610403e5**** for example. The **** is just a way of checking the start and end of the number that I have used in the past with non web based projects and could be changed.
Anyway to my question at last: As part of error checking I thought I would check for NaN as I do get NaN errors when I have been testing but while *1234 gives a positive NaN 12**34 does not, why is that? and what else can I do to test?
Here is some of the code I have used, please note I am fairly new to javascript.
function readSliceConvert()
{
functionReadForm()
testVal = hexString.slice(4,18);
document.getElementById("battDb4").innerHTML=testVal;
testNum1 = h2d(testVal)
document.getElementById("battDb5").innerHTML=testNum1.toString();
testNum2 = parseInt(testVal);
document.getElementById("battDb6").innerHTML=testNum2.toString();
if (isNaN(testNum2))
{
errorCount++;
document.getElementById("battDb3").innerHTML=errorCount.toString();
document.getElementById("battDb4").innerHTML=testVal;
return;
}
}

That's because you are using parseInt, it will silently ignore characters at the end of the string when there are some digit in the beginning of the string that it can parse.
I don't know what your h2d function is doing, but it seems that you are converting the hexadecimal string to a number, then to a string in decimal form, then back to a number. I don't see any reason why the output of parsing the hexadecimal string couldn't be a number.
For example like this, returning null if the parsing fails:
function h2i(str) {
var num = 0;
var digits = "0123456789abcdef";
str = str.toLowerCase();
for (var i = 0; i < str.length; i++) {
var n = digits.indexOf(str.substr(i, 1));
if (n == -1) return null;
num = num * 16 + n;
}
return num;
}
Demo: http://jsfiddle.net/Guffa/6yAaP/
Usage:
testVal = hexString.slice(4,18);
document.getElementById("battDb4").innerHTML = testVal;
testNum = h2i(testVal)
document.getElementById("battDb5").innerHTML = testNum.toString();
if (testNum == null)
{
errorCount++;
document.getElementById("battDb3").innerHTML = errorCount.toString();
document.getElementById("battDb4").innerHTML = testVal;
return;
}

Do you know what parseInt() does?
From MDN
parseInt is a top-level function and is not associated with any
object.
The parseInt function converts its first argument to a string, parses
it, and returns an integer or NaN. If not NaN, the returned value will
be the decimal integer representation of the first argument taken as a
number in the specified radix (base). For example, a radix of 10
indicates to convert from a decimal number, 8 octal, 16 hexadecimal,
and so on. For radices above 10, the letters of the alphabet indicate
numerals greater than 9. For example, for hexadecimal numbers (base
16), A through F are used.
If parseInt encounters a character that is not a numeral in the
specified radix, it ignores it and all succeeding characters and
returns the integer value parsed up to that point. parseInt truncates
numbers to integer values. Leading and trailing spaces are allowed.
Run the code in the console
console.log( parseInt("12**34",10) );
So you are running isNaN against a number since parseInt returns 12.
When you have the * as the first character, there are no leading numbers to return.
console.log( parseInt("*1234",10) );

You're seeing weird behaviour because isNan is broken (see the mozilla docs for details).
A better way to test your data is correctly formatted would be a quick regular expression, like serial.test(/^\d+$/), which will succeed if the entire serial is entirely numeric, or serial.test(/^\*{4}\d+\*{4}$/) which will succeed if the serial is four asterisks, followed by one or more number, followed by another four asterisks.
Update: #Guffa's answer is correct, and should be accepted, but I'll leave this here as I think there's a valid argument in the bigger picture that you could better accomplish what you're trying to do with a regular expression.
Running test on the string executes the supplied regular expression, and returns true if it matches the string.
Regular expressions are just patterns describing text, which can be incredibly complex or as simple as the example I've given (\d+ means match a number (\d) one or more times (+), with anchors for the beginning (^) and end ($) of the string to indicate that we want to match the whole string, not just part of it. They're ridiculously useful, so it's almost certainly worth taking the time to learn the basics of how they work, and expand you knowledge over time. There's a great tutorial on regular-expressions.info that'll get you started in no time.

Related

Check if no unicode character is associated with a number Javascript

I am making a base converter that can convert any number in any base to the same number in any other base. Since the bases could be any number the result could have digits that represent a number greater than 10. In order to have only one character correspond to each digit in the final result, I plan to assign Unicode characters to each digit corresponding to a value greater than 10 by using String.fromCharCode(Base 10 number digit represents). However, I noticed that there was a problem with this method; It seems as if a lot of the values are blank when outputted onto the HTML webpage or only output an empty box that looks like this: ⯣. When I tried to see if the value of the Unicode character equaled the empty box or an empty string by using an if statement, it always seemed to return false, even when the Unicode character associated with the digit returned the same empty box. Please may you help me understand why this is, and how I can construct the if statement such that it will work like I want it to?
You could try this:
function convertToDecimal(num, base) {
return window.parseInt(num.toString(), base);
}
const binary = 10;
const base = 2;
console.log("Decimal version:", convertToDecimal(binary, base))

Regular expression to ignore the numbers after length reaches 10

I want number in this format
(123)-456-7890
The maximum length assigned is 10.
The regular expression used to obtain the above format is:
if (onlyNums.length === 10) {
const number = onlyNums.replace(/(\d{3})(\d{3})(\d{4})/, '($1) -$2-$3');
If length>10 I want the above format for the number and to ignore the rest of the digits(right trim).
How can I do that?
If you remove the if condition and add a "catch-all" regex .* at the end, it will ignore whatever comes after the 10th digit:
const number = onlyNums.replace(/(\d{3})(\d{3})(\d{4}).*/, '($1) -$2-$3');
This assumes that onlyNums actually contains nothing but digits (and at least 10 of them). Otherwise, the result might be unexpected.
Test it live on regex101.com.

Why do trailing and leading zeros cause my function to return values i do not want?

This set of code i am providing should take any number i enter and reverse it. Currently the function works when n = 21.365 or n = 5698 but when n = 0456456456 it returns 41422397 instead of 6546546540 or when n = 056985 it returns 58965 instead of 589650 and when n = 016540 it returns 257 instead of 45610.
This is what i have written so far
//rules & limitations
//negative numbers should remain negative
//leading zeros should be removed
//the function can accept floats or integers
//the function will return integers as integers
function reverseNumberWithBuiltInFunctions(n) {
return (
parseFloat (
n
//convert the number to a string
.toString()
//convert to array of characters
.split('')
//reverse array of characters
.reverse()
//join reversed array of characters
.join('')
) * Math.sign(n)
)
}
I would like if n = 001 then 100 is returned or if n = 0456456456 then 6546546540 is returned. Essentially i am having trouble when leading or trailing zeros or both are included in "n" or it seems like issues arise when there is some sort of pattern to the numbers.
Also, why is it that when n = 016540 it returns 257?
Do you know of any solutions that could help improve the logic of the function with the given rules and limitations that would yield the desired results?
What you want is impossible if the inputs are integers or floats. There is no such thing as "leading zeros" on either integers or floats. If you use leading zeros to make a integer literal, it becomes an octal literal (changing the value; that's why n = 0456456456 behaves the way it does, 0456456456 is just the octal way to spell 79322414). If you parse a string with leading zeros to make an integer, they're simply ignored (parseInt('000123') produces the same value as parseInt('123'), namely, the value 123). That's why 016540 becomes 257: the octal literal is equivalent to the decimal literal 7520, and reversing it and parsing back to integer ignores the leading 0, leaving 257.
You can't preserve such leading zeros because they don't exist outside of string form. And you'll lose the trailing zeros on reversal because they become leading zeros in the new form.
Either work with strings exclusively, or accept that you'll lose leading zeros.
I'll note that your own rules in the comments specify:
//leading zeros should be removed
so it's working as expected here.
You have to pass it in as a string as leading 0's in your numbers will not be interpreted as such.
For example:
// Will always be evaluated as 1
let foo = 001;
console.log(foo);
If you were to supply n as a string, you may do it like this:
reverseNumberWithBuiltInFunctions = n => parseFloat(n.toString().split('').reverse().join(''));
console.log(reverseNumberWithBuiltInFunctions('0456456456'))
console.log(reverseNumberWithBuiltInFunctions('056985'))

Algorithm for javascript pre-defined functions (parseInt, parseFloat, isNaN, etc.)

What is the best way, if even possible, to see the underlying code for the predefined functions in Javascript. Is there documentation that shows how these were coded, or an easy way to actually view the underlying code?
parseInt
parseFloat
isNaN
They are native functions, and maybe coded in the language your JS engine was written in - you'd need to contact it's source.
However, you probably are more interested in the EcmaScript specification that describes how the algorithms work.
And if you're lucky, for some of the functions you even might find an JS equivalent. You'll find them mostly on pages that test ES implementations against the standard.
After looking further I found this in the ECMAScript specification.
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
When the parseInt function is called, the following steps are taken:
Let inputString be ToString(string).
Let S be a newly created substring of inputString consisting of the first character that is not a
StrWhiteSpaceChar and all characters following that character. (In other words, remove leading white
space.) If inputString does not contain any such characters, let S be the empty string.
Let sign be 1.
If S is not empty and the first character of S is a minus sign -, let sign be 1.
If S is not empty and the first character of S is a plus sign + or a minus sign -, then remove the first character
from S.
Let R = ToInt32(radix).
Let stripPrefix be true.
If R  0, then© Ecma International 2011 105
a. If R < 2 or R > 36, then return NaN.
b. If R  16, let stripPrefix be false.
Else, R = 0
a. Let R = 10.
If stripPrefix is true, then
a. If the length of S is at least 2 and the first two characters of S are either ―0x‖ or ―0X‖, then remove
the first two characters from S and let R = 16.
If S contains any character that is not a radix-R digit, then let Z be the substring of S consisting of all
characters before the first such character; otherwise, let Z be S.
If Z is empty, return NaN.
Let mathInt be the mathematical integer value that is represented by Z in radix-R notation, using the letters
A-Z and a-z for digits with values 10 through 35. (However, if R is 10 and Z contains more than 20
significant digits, every significant digit after the 20th may be replaced by a 0 digit, at the option of the
implementation; and if R is not 2, 4, 8, 10, 16, or 32, then mathInt may be an implementation-dependent
approximation to the mathematical integer value that is represented by Z in radix-R notation.)
Let number be the Number value for mathInt.
Return sign  number.
NOTE parseInt may interpret only a leading portion of string as an integer value; it ignores any characters that
cannot be interpreted as part of the notation of an integer, and no indication is given that any such characters were
ignored.
When the parseFloat function is called, the following steps are taken:
Let inputString be ToString(string).
Let trimmedString be a substring of inputString consisting of the leftmost character that is not a
StrWhiteSpaceChar and all characters to the right of that character. (In other words, remove leading white
space.) If inputString does not contain any such characters, let trimmedString be the empty string.
If neither trimmedString nor any prefix of trimmedString satisfies the syntax of a StrDecimalLiteral (see
9.3.1), return NaN.
Let numberString be the longest prefix of trimmedString, which might be trimmedString itself, that satisfies
the syntax of a StrDecimalLiteral.
Return the Number value for the MV of numberString.
NOTE parseFloat may interpret only a leading portion of string as a Number value; it ignores any characters that
cannot be interpreted as part of the notation of an decimal literal, and no indication is given that any such characters were
ignored.
Returns true if the argument coerces to NaN, and otherwise returns false.
If ToNumber(number) is NaN, return true.
Otherwise, return false.
NOTE A reliable way for ECMAScript code to test if a value X is a NaN is an expression of the form X !== X. The
result will be true if and only if X is a NaN.
Those functions are implementation specific depending on browser, and are not written in JS (unless somebody's decided to write a browser engine in JS). The code is not guaranteed to be the same across environments, though they do have to (in theory) adhere to the ECMAScript specification for their behavior.

Javascript, why treated as octal

I'm passing as parameter an id to a javascript function, because it comes from UI, it's left zero padded. but it seems to have (maybe) "strange" behaviour?
console.log(0000020948); //20948
console.log(0000022115); //9293 which is 22115's octal
console.log(parseInt(0000022115, 10)); // 9293 which is 22115's octal
console.log(0000033959); //33959
console.log(20948); //20948
console.log(22115); //22115
console.log(33959); //33959
how can I make sure they are parsing to right numebr they are? (decimal)
EDIT:
just make it clearer:
those numbers come from the server and are zero padded strings. and I'm making a delete button for each one.
like:
function printDelButton(value){
console.log(typeof value); //output string
return '<img src="images/del.png">'
}
and
function printDelButton(value){
console.log(typeof value); //output numeric
console.log(value); //here output as octal .... :S
}
I tried :
console.log(parseInt(0000022115, 10)); // 9293 which is 22115's octal
and still parsing as Octal
If you receive your parameters as string objects, it should work to use
parseInt(string, 10)
to interpret strings as decimal, even if they are beginning with 0.
In your test, you pass the parseInt method a number, not a string, maybe that's why it doesn't return the expected result.
Try
parseInt('0000022115', 10)
instead of
parseInt(0000022115, 10)
that does return 221115 for me.
If you start it with a 0, it's interpreted as an Octal number.
See http://www.hunlock.com/blogs/The_Complete_Javascript_Number_Reference#quickIDX2
Note the article's warning here:
You should never precede a number with a zero unless you are
specifically looking for an octal conversion!
Consider looking here for ideas on removing the leadings 0s:
Truncate leading zeros of a string in Javascript
Leading 0s indicate that the number is octal.
parseInt parses a string containing a number.
parseInt(0000022115, 10) passes a numeric literal. The literal is parsed in octal by the JS interpreter, so you're passing a raw numeric value to parseInt.
Unless you can intercept a string version of this number, you're out of luck.
That being said, if you can get a string version of your octal (calling toString() won't help), this will work:
parseInt(variable_string.replace(/^0+/, ''), 10);
Try
/^[0]*([1-9]\d)/.exec(numberFromUI)[0]
That should give you just the numbers stripping the zeros (if you have to support decimals, you'll need to edit to account for the '.', and of course ',' is fun too... and I really hope you don't have to handle all the crazy different ways Europeans write numbers! )
If number came from server as zero padded string then use +"0000022115"
console.log(+"0000022115")
if (021 < 019) console.log('Paradox');
JS treat zero padded numbers like octal only if they are valid octal - if not then it treat it as decimal. To not allow paradox 'use strict' mode
'use strict'
if (021 < 019) console.log('Paradox');

Categories