Converting roman numbers to integers - javascript

I want to replace certain strings (roman numbers) in a string with nodejs.
A simple concatenation of .replace() is not working as expected, because obviously some roman numbers are contained with other roman numbers. That sounds awful, but this example explains:
"III".replace('I', '1');
// "111";
offcourse we can reorder the .replace() methods to surpress this behaviour, like so:
"III".replace('III', '3').replace('II', '2').replace('I', '1');
// "3"
But then with XI we get into trouble.
Is there a smarter way to do this?

Of course. You have to add the numbers. For example:
"111" could be 1+1+1 = 3
You have to be sure that sometimes an small number on the left of a bigger number should substract in the final number. So if you validate that it's really easy.
For example:
"IV" = 4
I = 1
V = 5
I<V
So, the result will be:
5-1 = 4
The number 1 should be substracted because is on the left of a bigger number.

Related

How to avoid "Infinity" and console.log a large number in Javascript?

I am trying to find the first number in the Fibonacci sequence to contain over 1000 digits.
Given a number n (e.g. 4), I found a way to find what place the first number with n-digits has in the Fibonacci sequence as well as a way to find the number given its place in the sequence.
Say, for example, you need to know the first number with 4 digits in the Fibonacci sequence as well as its place in the sequence. My code would work like this:
var phi = (1+Math.sqrt(5))/2;
var nDigits = 4;
var fEntry = Math.ceil(2 + Math.log(Math.pow(10, nDigits-
1))/Math.log(phi));
var fNumber = 2 * Math.pow(phi, fEntry);
console.log(fEntry);
console.log(fNumber);
In the console you would see fEntry (that is, the place the number has in the Fibonacci sequence) and fNumber (the number you're looking for). If you want to find the first number with 4 digits and its place in the sequence, for example, you'll get number 1597 at place 17, which is correct.
So far so good.
Problems arise when I want to find big numbers. I need to find the first number with 1000 digits in the Fibonacci sequence, but when I write nDigits = 1000 and run the code, the console displays "Infinity" for fEntry and for fNumber. I guess the reason is that my code involves calculations with numbers higher than what Javascript can deal with.
How can I find that number and avoid Infinity?
How can I find that number and avoid Infinity?
You can't, with the number type. Although it can hold massive values, it loses integer accuracy after Number.MAX_SAFE_INTEGER (9,007,199,254,740,991):
const a = Number.MAX_SAFE_INTEGER;
console.log(a); // 9007199254740991
console.log(a + 1); // 9007199254740992, so far so good
console.log(a + 2); // 9007199254740992, oh dear...
You can use the new BigInt on platforms that support it. Alternately, any of several "big int" libraries that store the numbers as strings of digits (literally).

Fixed Length Number with Decimals as well

I have a number of variable length the looks something like this:
48.4532
I want to convert it to 4 digits before decimal and 2 decimal places, so the number above should be:
0048.45
I also don't want to show decimals unless they are necessary, so:
48
should become:
0048
I was able to get the fixed length, but I couldn't get the decimals to show up only if they were necessary (I don't want to show two 0's at the end).
This is how I got a fixed length:
trackPartLength = ("0000" + trackPartLength.toString()).slice(-4); // Convert to fixed length
How do I add the 2 decimal points only if they are needed?
Edit: I also just realized that if the number does have decimals with the above code, it moves the decimal point over 4 spots causing some other problems, so I'm not sure if my initial approach is a good one. I'm trying to right a fixed length function of variable fixed prefix and decimal length.
This should work:
trackPartLength = ("0000" + trackPartLength.toFixed(2)).slice(-7).replace( /\.00$/, '' );
It uses toFixed to get the two decimal points, zero pads and then removes any trailing .00. Examples:
48.4532 -> 0048.45
48 -> 0048
6.213 -> 0006.21
12345 -> 2345
1234.56789 -> 1234.57
If the number can have more than four digits before the decimal, as in the 12345 example, you may want to make the zero padding and slice conditional, so that you don't remove leading digits from a big number. That could be done like this:
var tmp = trackPartLength.toFixed(2);
trackPartLength = (tmp.length >= 7 ? tmp : ('0000' + tmp).slice(-7)).replace( /\.00$/, '' );

How can I parse a string as an integer and keep decimal places if they are zeros?

I have these strings: "59.50" & "30.00"
What I need to do is convert them to integers but keep the trailing zeros at the end to effectively return:
59.50
30.00
I've tried:
Math.round(59.50 * 1000) / 1000
Math.round(30.00 * 1000) / 1000
but ended up with
59.5
30
I'm assuming I need to use a different method than Math.round as this automatically chops off trailing zeros.
I need to keep these as integers as they need to be multiplied with other integers and keep two decimals points. T thought this would be fairly straight forward but after a lot of searching I can't seem to find a solution to exactly what I need.
Thanks!
Your premise is flawed. If you parse a number, you are converting it to its numerical representation, which by definition doesn't have trailing zeros.
A further flaw is that you seem to think you can multiply two numbers together and keep the same number of decimal places as the original numbers. That barely makes sense.
It sounds like this might be an XY Problem, and what you really want to do is just have two decimal places in your result.
If so, you can use .toFixed() for this:
var num = parseFloat("59.50");
var num2 = parseFloat("12.33");
var num3 = num * num2
console.log(num3.toFixed(2)); // 733.64
Whenever you want to display the value of the variable, use Number.prototype.toFixed(). This function takes one argument: the number of decimal places to keep. It returns a string, so do it right before viewing the value to the user.
console.log((123.4567).toFixed(2)); // logs "123.46" (rounded)
To keep the decimals - multiply the string by 1
example : "33.01" * 1 // equals to 33.01
Seems you are trying to retain the same floating point, so better solution will be some thing like
parseFloat(string).toFixed(string.split('.')[1].length);
If you want numbers with decimal points, you are not talking about integers (which are whole numbers) but floating point numbers.
In Javascript all numbers are represented as floating point numbers.
You don't need the trailing zeros to do calculations. As long as you've got all the significant digits, you're fine.
If you want to output your result with a given number of decimal values, you can use the toFixed method to transform your number into a formatted string:
var num = 1.5
var output = num.toFixed(2) // '1.50'
// the number is rounded
num = 1.234
output = num.toFixed(2) // '1.23'
num = 1.567
output = num.toFixed(2) // '1.57'
Here's a more detailed description of toFixed: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed

Remove last digits from an int

Can't seem to find a good answer to this question. How do I remove the last 11 digits from an int?
The id could be one or more numbers in the beginning but there will always be 11 digits following the id. There will always be an id in the beginning. {id}{11 digits}.
var getId = function (digits) {
// Do some stuff and return id
}
getId(110000000001); // Should return 1
getId(1110000000001); // Should return 11
getId(2010000000001); // Should return 20
Divide by 1e11 and take the floor:
var stripped = Math.floor(id / 1e11);
This avoids conversion to/from a string representation.
Note that the nature of JavaScript numerics is such that your "raw" values (the values with the 11 useless digits) can't have more than 5 digits in addition to those 11 before you'll start running into precision problems. I guess if you never care about the low-order 11 digits that might not be a problem.
Try this:
var str = 1100000000011;
var res = str.toString().substr(0, str.toString().length - 11);
Demo
You can convert your number to string and delete tailing digits:
digits.toString().replace(/\d{11}$/, '')
By the way, you better don't use ints (or to be precise, Numbers) because if number is greater than 2147483648 (by absolute value), it'll be represented internally as double resulting in precision loss. If don't need tailing digits, then it's okay — use division approach suggested in other answers (this one could break because of scientific notation). But if you want to keep all the data, you should represent your numbers with strings.
You can use division and 10^11 to do so.
Edit: my bad
var getId = function (digits) {
var id = parseInt((digits/(1e11)),0);
}
You can convert the number to a string and slice the last 11 characters from the end
parseInt( digits.toString().slice(0, -11) );
Using .slice( 0 , [ negative_number ]); will slice x characters from the end of the string
More information on .slice() Here

Convert a Decimal number to float and truncate it

I have a number
For example:
8183
What I need is to convert it to a float number-
For example 8183
(8183).toFixed(2);
will return me
8183.00
But I need to truncate it further, so the final number will be
8.18
So basically I need to make it float number with just 2 decimal places.
I tried using the Math.floor and ceil but couldnt figure it out!
Well what you're trying to accomplish is not completely clear, but I think that if you start by dividing by 1000, then call toFixed on it, it will give you the desired result.
var before = 8183;
var after = (before / 1000).toFixed(2); //8.18
You could divide by 10 until you are less than 10:
var digits = 8183;
while((digits = digits/10) > 10) {}
digits = digits.toFixed(2); // 8.18
For negative numbers, you could want to store a boolean value and use Math.abs(digits).
For numbers less than 0, you would want to multiple instead of divide.
If all you really want is scientific notation use toExponential(2)

Categories

Resources