Regex for finding all the numbers between any two numeric values (range) in JavaScript [duplicate] - javascript

This question already has answers here:
How to match numbers between X and Y with regexp?
(7 answers)
Closed 7 years ago.
First of all, i know Regular expressions isn't the best tool to achieve what I want here. I have done enough research to know that bit. Still, The problem I am stuck in requires me to make up a regex to find the values between some lower and upper bound values.
So here is the problem, I have a large set of data, let's say ranging between 1 and 1000000. That data is not under my direct control, I cannot manipulate the data directly. Only way of finding out (searching) some values from that data is regex.. Now, the user can give two values, a minimum value and a maximum value and I need to construct a regex based on these two values and then query the large data set using the regex to get all the values lying between the set range. So, if my data contains [1,5,7,9,15,30,45,87] and user sets the range min:10, max:40. The regex should filter out values 15, 30.
From whatever I have searched, I know it is very much possible to build a regex for finding out values between fixed values (if we know them beforehand) for example, values between 1 to 100 can be found by:
^(100|[1-9][0-9]?)$
But what gets so tricky about my problem is that the input range can be anything from pretty much 1 digit values to up to 10 digit values. 10000-550000 can be an example user input for a large data set.
I know this will require some complex logic and loops involved on the basis of number of digits in the lower bound and number of digits in the upper bound of the range and then some recursive or other magical logic to build a regex that covers all the number lying in that range.
I've been filling up pages to come up with a logic but I'm afraid it surpasses my knowledge of regex. If anyone has ever done something like this before or try to point me in the right direction or attempt it him/herself - it'll be quite helpful. Thanks.
The language I will be using this in is JavaScript and I read somewhere that JS doesn't support conditional regex, keeping that in mind, solution doesn't have to be in specific to a language.

If your task is to get numbers between min and max value from the dataset, you can try filter method.
Var filteredResults = Dataset.filter(function(item){
If(item < max && item > min)
Return item
}
)

Related

Why does a number get its last 2 digits turned to 0?

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.

What is the best way to make a prompt into an integer in JS? [duplicate]

This question already has answers here:
How to get numeric value from a prompt box? [duplicate]
(6 answers)
Closed 9 months ago.
I am writing a program to perform "Russian Math" (using the numberphile youtube video on it as my basis for the algorithm). It works. But, to "prove" that it works, I'm giving the user the ability to try using their own numbers as input.
When I assign numbers to the variables myself, it works without fail. However, when I use prompt var numberOne = prompt('What is the first number you want to multiply?'); on one variable (with the other being assigned myself)it works. But as soon as I prompt the user for both numbers it won't work. Presumably because a string can be converted to an integer when an operation is performed on it (multiplied by an integer), but it does not seem to work when both are strings.
Adding another line to reset the prompt variable to an integer using parse seems like too much extra.
var numberOne = prompt('What is the first number you want to multiply?');
var numberTwo = prompt('What is the second number you want to multiply?');
var numberOneInt = parseInt(numberOne);
var numberTwoInt = parseInt(numberTwo);
Is this really the best way to do it?
For a prompt, yes, that is pretty much what you want to do. Prompt returns a string, so you need to convert it. There are other ways, i.e. Number(numberOne), but parseInt is fine. They have slightly different behaviors, but for your case they're mostly the same. (parseInt stops parsing at the first non-number, while Number type-casting attempts to convert the whole thing).
And kudos for figuring out the edge behavior of having one string and one int multiplied together.
In general, most developers prefer using inputs on the page rather than prompts. The problem with prompts is that they interrupt the user's control of the page. As a bonus, with inputs you can set type=number to give the users number controls on some devices and limit the input to actual numbers.
Edit
I don't ever use prompt, so I was reading up on them. One thing to look out for is if the user hits escape, it returns null, which may break your code. You could prevent that by just checking for it first, i.e. if(numberOne){ ... }

Why doesn't my function correctly replace when using some regex pattern

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.

How to "unformat" a numerical string? JavaScript

So I know how to format a string or integer like 2000 to 2K, but how do I reverse it?
I want to do something like:
var string = "$2K".replace("/* K with 000 and remove $ symbol in front of 2 */");
How do I start? I am not very good regular expressions, but I have been taking some more time out to learn them. If you can help, I certainly appreciate it. Is it possible to do the same thing for M for millions (adding 000000 at the end) or B for billions (adding 000000000 at the end)?
var string = "$2K".replace(/\$(\d+)K/, "$1000");
will give output as
2000
I'm going to take a different approach to this, as the best way to do this is to change your app to not lose the original numeric information. I recognize that this isn't always possible (for example, if you're scraping formatted values...), but it could be useful way to think about it for other users with similar question.
Instead of just storing the numeric values or the display values (and then trying to convert back to the numeric values later on), try to update your app to store both in the same object:
var value = {numeric: 2000, display: '2K'}
console.log(value.numeric); // 2000
console.log(value.display); // 2K
The example here is a bit simplified, but if you pass around your values like this, you don't need to convert back in the first place. It also allows you to have your formatted values change based on locale, currency, or rounding, and you don't lose the precision of your original values.

Regex - creating an input/textarea that correctly interprets numbers

Im designing a conversion website where i perform calculations on inputted numbers and i need my input or textarea to receive and interpret numbers entered in different fashions
like:
Entry = 3,000,000.1111
Interpreted value = 3000000.1111
or
Entry = 3000000.1111
Interpreted value = 3000000.1111
and I want to include a second input for European decimal notation
(or if possible have the same input do both)
Entry = 3.000.000,1111 (comma acts a decimal, decimal as separator)
Interpreted value = 3000000.1111
I wonder how I could do this. I suspect from some of my research that I could use regex.
Also should i use an input or a textarea? I want to limit the size of the number to 40 places.
It seems the textarea Im currently using won't recognize any values after a comma when a comma is used. I realized this is due to parseFloat. So I need to remove the commas using .replace() before parsing. But what do I do in the instance of European notation where the comma IS the decimal point? I suspect I should use regex to identify if a number is in comma decimal notation or standard decimal point notation and then outline the appropriate replacement behavior based on that. Any ideas how to write regex to identify a number between .0000000001 and 1,000,000,000,000,000 by only the separator and decimal point? What about when the entry doesn't use either? 12000 for example. Any help with this would be appreciated. Using HTML5 and Javascript. I am not using a form and am new at this. This is my first web page so please be patient with my questions.
I was thinking about this:
input = //value from textarea as a string
if(/REGEX which determines that the structure of the number is N,NNN.NN/.test(input)){
input = input.replace(/\,/,""); //replace the commas with nothing
}
else if(/REGEX which determine that structure of the number is N.NNN,NN/.test(input){
input = input.replace(/\./,""); //replace the decimal point separators with nothing
input = input.replace(/\,/,".");//replace the comma decimal with a point decimal
}
else{
//input unchanged assuming is NNNN without decimal
}
number = parseFloat(input);
I want to keep the possibility open for them to enter large numbers and also to use numbers less than one to 10 decimal places. Thanks to those who contributed.
Best,RP
I believe this should handle everything:
^[1-9](?:\d{0,2}(?:([,.])\d{3})*|\d+)(?:(?!\1)[,.]\d+)?$
You're treading on complicated territory here. Also, the above RegEx does not allow for values less than "1".
Basically, the RegEx does the following:
Allows for no thousandths separators ("," or ".") but ensures if they are used that they occur in the correct places.
Allows for either "," or "." to be used as both thousandths/cents separators, but ensures that the cents separator is not the same as the thousandths separator.
Requires the string equivalent number to begin with any digit other than "0".
To implement this you could attach an event listener to your form element(s) and use JS to do a simple .test.
After reading further, I think I misinterpreted your goal originally. I assumed you simply wanted to validate these values with a RegEx. I also assumed you're trying to work with currency (ie. two decimal places). However, fret not! You can still utilize my original answer if you really want.
You mentioned input and textarea which are both form elements. You can attach a listener to these element(s) looking for the input, change, and/or keyup events. As a part of the callback you can run the .test method or some other functionality. Personally, I would rethink how you want to handle input. Also, what's your actual goal here? Do you really need to know the thousandths separator or keep track of it? Why not just disallow any characters other than the one decimal point/comma and digits?
Also, parsing numbers like .0000000001 as a float is a terrible idea. You will lose precision very quickly if you do any sort of calculations such as multiplication, division, power, etc. You're going to have to figure out a different method to do this like storing the number to the right separately and as integers instead then go from there.
I can help you if you describe what you're trying to do in better detail.

Categories

Resources