I have five digit US zip codes coming out of the database. When JavaScript see them, it treats them as a number and lops off the leading zeros.
How do I get JavaScript to treat the numbers as a string so that they display correctly?
Quote them.
In both JavaScript and JSON 05123 is an octal number equal to 2643 (thanks #Marc B) and "05123" is a string containing only numeric characters.
Don't quote them in your database, of course. You'll want to quote them in the JavaScript or JSON you are generating in the server-side code that's reading the information from the database and passing it to your client-side code. Ordinarily, that's as simple as casting the zip code to a string (or, as is the more likely case, not casting your numeric zips to a number.)
Here's a function which pads a number until it's 5 characters long.
function formatzip(num) {
var s = "00000"+num;
return s.substr(s.length-5);
}
But really the zip code should never have turned into a number in the first place. It should be a string when you set it's value to begin with.
I'm sure that String() would probably work. If by that time, the 0s are already lopped off, you could do something like:
zip = <Source>;
zip = String(zip);
while(zip.length<5){
zip = "0" + zip;
}
Tell me if this isn't what you're looking for.
A guess... Some genius decided to store ZIP codes in a numeric column type inside the database (NUMBER, INT or whatever type your DBMS implements). If that was the case, all ZIP codes that start with zero are already corrupted.
It'd be better to switch the column to VARCHAR before it's too late and fix the corrupted rows manually.
Related
Use
Hi, so I was working on my discord bot with some user ids that I stored in a database, which then I will get back to ping them or give them roles.
Problem
Though here's the problem, in the database they get turned from ex: 533692905387196429 to 533692905387196400. I tried setting that to a String, and it worked, in the database, it's stored fully how it's supposed to be. But, when I get them back from the database and turn them into a number or an integer they get turned back to ex: 533692905387196400.
Tried using
I tried using parseInt(), parseFloat() and Number() but all of them give the same result.
More info
Also if I remove 2 digits for example: 533692905387196429I remove 19 from there, it will give back 533692905387(19)6429 instead of 533692905387196429 and instead of 533692905387196400.
Any help is appreciated!
So, Number.MAX_SAFE_INTEGER is 9007199254740991 (which is 253 - 1). Your number is too large to hold full precision.
If you want a number with that level of digits and precision, you can use BigInt and then you will have to be very careful how you use that BigInt as it cannot be directly used in place of a regular Number type, but it can hold infinite precision and you can do math between two BigInt values.
Whether it's best used as a BigInt or as a String really depends upon what you're doing with it. If these are just some sort of ID that you aren't actually doing numeric operations with, then you can just keep it as a string.
The number is too big, so Javascript doesn't keep full precision!
> 533692905387196429
533692905387196400
You can resolve this by storing them as strings:
> '533692905387196429'
'533692905387196429'
You shouldn't need to do any mathematical operations with Discord IDs so there shouldn't be any issue storing and treating them as strings everywhere.
This is an extension of this SO question
I made a function to see if i can correctly format any number. The answers below work on tools like https://regex101.com and https://regexr.com/, but not within my function(tried in node and browser):
const
const format = (num, regex) => String(num).replace(regex, '$1')
Basically given any whole number, it should not exceed 15 significant digits. Given any decimal, it should not exceed 2 decimal points.
so...
Now
format(0.12345678901234567890, /^\d{1,13}(\.\d{1,2}|\d{0,2})$/)
returns 0.123456789012345678 instead of 0.123456789012345
but
format(0.123456789012345,/^-?(\d*\.?\d{0,2}).*/)
returns number formatted to 2 deimal points as expected.
Let me try to explain what's going on.
For the given input 0.12345678901234567890 and the regex /^\d{1,13}(\.\d{1,2}|\d{0,2})$/, let's go step by step and see what's happening.
^\d{1,13} Does indeed match the start of the string 0
(\. Now you've opened a new group, and it does match .
\d{1,2} It does find the digits 1 and 2
|\d{0,2} So this part is skipped
) So this is the end of your capture group.
$ This indicates the end of the string, but it won't match, because you've still got 345678901234567890 remaining.
Javascript returns the whole string because the match failed in the end.
Let's try removing $ at the end, to become /^\d{1,13}(\.\d{1,2}|\d{0,2})/
You'd get back ".12345678901234567890". This generates a couple of questions.
Why did the preceding 0 get removed?
Because it was not part of your matching group, enclosed with ().
Why did we not get only two decimal places, i.e. .12?
Remember that you're doing a replace. Which means that by default, the original string will be kept in place, only the parts that match will get replaced. Since 345678901234567890 was not part of the match, it was left intact. The only part that matched was 0.12.
Answer to title question: your function doesn't replace, because there's nothing to replace - the regex doesn't match anything in the string. csb's answer explains that in all details.
But that's perhaps not the answer you really need.
Now, it seems like you have an XY problem. You ask why your call to .replace() doesn't work, but .replace() is definitely not a function you should use. Role of .replace() is replacing parts of string, while you actually want to create a different string. Moreover, in the comments you suggest that your formatting is not only for presenting data to user, but you also intend to use it in some further computation. You also mention cryptocurriencies.
Let's cope with these problems one-by-one.
What to do instead of replace?
Well, just produce the string you need instead of replacing something in the string you don't like. There are some edge cases. Instead of writing all-in-one regex, just handle them one-by-one.
The following code is definitely not best possible, but it's main aim is to be simple and show exactly what is going on.
function format(n) {
const max_significant_digits = 15;
const max_precision = 2;
let digits_before_decimal_point;
if (n < 0) {
// Don't count minus sign.
digits_before_decimal_point = n.toFixed(0).length - 1;
} else {
digits_before_decimal_point = n.toFixed(0).length;
}
if (digits_before_decimal_point > max_significant_digits) {
throw new Error('No good representation for this number');
}
const available_significant_digits_for_precision =
Math.max(0, max_significant_digits - digits_before_decimal_point);
const effective_max_precision =
Math.min(max_precision, available_significant_digits_for_precision);
const with_trailing_zeroes = n.toFixed(effective_max_precision);
// I want to keep the string and change just matching part,
// so here .replace() is a proper method to use.
const withouth_trailing_zeroes = with_trailing_zeroes.replace(/\.?0*$/, '');
return withouth_trailing_zeroes;
}
So, you got the number formatted the way you want. What now?
What can you use this string for?
Well, you can display it to the user. And that's mostly it. The value was rounded to (1) represent it in a different base and (2) fit in limited precision, so it's pretty much useless for any computation. And, BTW, why would you convert it to String in the first place, if what you want is a number?
Was the value you are trying to print ever useful in the first place?
Well, that's the most serious question here. Because, you know, floating point numbers are tricky. And they are absolutely abysmal for representing money. So, most likely the number you are trying to format is already a wrong number.
What to use instead?
Fixed-point arithmetic is the most obvious answer. Works most of the time. However, it's pretty tricky in JS, where number may slip into floating-point representation almost any time. So, it's better to use decimal arithmetic library. Optionally, switch to a language that has built-in bignums and decimals, like Python.
I use the new Parse Server, and in the cloud part which is using Javascript I want to check if an integer is specified by a user, in other words I want to check if the Int is null or not. I can do it for strings, but as I see from comments, an int can not be null. Bu I do not want to change all ints in my code to integers. I try the code below, but it is not working, how can I check if there is a number specified by the user or if it is empty?
if (!req.object.get('number'))
Your code should work as long as number isn't zero. To handle that case as well, simply do a type check like this:
if (typeof req.object.get('number') !== 'number').
It seems like you are confusing java and javascript. Javascript does not have ints or integers, only numbers. Javascript variables do not have types and all variables can be null and undefined.
I have the following JSON:
[{"hashcode": 4830991188237466859},{...}]
I have the following Angular/JS code:
var res = $resource('<something>');
...
res.query({}, function(json) {hashcode = json[0].hashcode;};
...
Surprisingly (to me, I'm no JS expert), I find that something (?) is rounding the value to the precision of 1000 (rounding the last 3 digits). This is a problem, since this is a hash code of something.
If, on the other hand I write the value as a String to the JSON, e.g -
[{"hashcode": "4830991188237466859"},{...}]
this does not happen. But this causes a different problem for me (with JMeter/JSON Path, which extracts the value ["4830991188237466859"] by running my query $.hashcode - which I can't use as a HTTP request parameter (I need to add ?hashcode=... to the query, but I end up with ?hashcode=["..."]
So I appreciate help with:
Understanding who and why -- is rounding my hash, and how to avoid it
Help with JMeter/JSON Path
Thanks!
Each system architecture has a maximum number it can represent. See Number.MAX_VALUE or paste your number into the console. You'll see it happens at the JavaScript level, nothing to do with angular. Since the hash doesn't represent the amount of something, it's perfectly natural for it to be a string. Which leads me to
Nothing wrong with site.com/page?hashcode=4830991188237466859 - it's treated as a string there and you should keep treating it as such.
The javascript Number type is floating point based, and can only represent all integers in the range between -253 and 253. Some integers outside this range are therefore subject to "rounding" as you experience.
In regards to JMeter JSON Path Extractor plugin, the correct JSON Path query for your hashcode will look like
$..hashcode[0]
See Parsing JSON chapter of the guide for XPath to JSON Path mappings and more details.
I need to parse a json that contains a long number (that was produces in a java servlet). The problem is the long number gets rounded.
When this code is executed:
var s = '{"x":6855337641038665531}';
var obj = JSON.parse(s);
alert (obj.x);
the output is:
6855337641038666000
see an example here: http://jsfiddle.net/huqUh/
why is that, and how can I solve it?
As others have stated, this is because the number is too big. However, you can work around this limitation by sending the number as a string like so:
var s = '{"x":"6855337641038665531"}';
Then instead of using JSON.parse(), you can use a library such as javascript-bignum to work with the number.
It's too big of a number. JavaScript uses double-precision floats for numbers, and they have about 15 digits of precision (in base 10). The highest integer that JavaScript can reliably save is something like 251.
The solution is to use reasonable numbers. There is no real way to handle such large numbers.
The largest number JavaScript can handle without loss of precision is 9007199254740992.
I faced this issue some time ago, I was able to solve using this lib: https://github.com/josdejong/lossless-json
You can check this example:
let text = '{"normal":2.3,"long":123456789012345678901,"big":2.3e+500}';
// JSON.parse will lose some digits and a whole number:
console.log(JSON.stringify(JSON.parse(text)));
// '{"normal":2.3,"long":123456789012345680000,"big":null}' WHOOPS!!!
// LosslessJSON.parse will preserve big numbers:
console.log(LosslessJSON.stringify(LosslessJSON.parse(text)));
// '{"normal":2.3,"long":123456789012345678901,"big":2.3e+500}'