String to integer leetcode - javascript

I was doing following leetcode question
Implement atoi which converts a string to an integer.
The function first discards as many whitespace characters as necessary
until the first non-whitespace character is found. Then, starting from
this character, takes an optional initial plus or minus sign followed
by as many numerical digits as possible, and interprets them as a
numerical value.
The string can contain additional characters after those that form the
integral number, which are ignored and have no effect on the behavior
of this function.
If the first sequence of non-whitespace characters in str is not a
valid integral number, or if no such sequence exists because either
str is empty or it contains only whitespace characters, no conversion
is performed.
If no valid conversion could be performed, a zero value is returned.
Note:
Only the space character ' ' is considered as whitespace character.
Assume we are dealing with an environment which could only store
integers within the 32-bit signed integer range: [−231, 231 − 1]. If
the numerical value is out of the range of representable values,
INT_MAX (231 − 1) or INT_MIN (−231) is returned.
Question link: https://leetcode.com/problems/string-to-integer-atoi/
Here for this input "-91283472332", I am not sure why do they expect the following output -2147483648 instead of -91283472332
Not sure, If this relevant but this is my code
/**
* #param {string} str
* #return {number}
*/
var myAtoi = function(str) {
let i = 0
let output = ''
let nonWhiteCharacter = false
while (i<str.length) {
const char = str[i]
if (!char == " ") {
if (char.toLowerCase() === char.toUpperCase()) {
if (!nonWhiteCharacter) nonWhiteCharacter = true
output = output + char
}
if (!nonWhiteCharacter) return 0
}
i++
}
return output === null ? 0 : parseInt(output)
}

I am not sure why do they expect the following output -2147483648 instead of -91283472332
Because:
Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. If the numerical value is out of the range of representable values, INT_MAX (231 − 1) or INT_MIN (−231) is returned.
So if the extracted number is larger than 2 ** 31 - 1, the returned number should be 2 ** 31 - 1 instead.
Similarly, if the extracted number is smaller than -(2 ** 31), instead return -(2 ** 31).
This would probably be easier with a regular expression:
const myAtoi = (str) => {
const match = str.match(/^ *([+-]?\d+)/);
if (!match) return;
const num = Number(match[1]);
return Math.max(
Math.min(2 ** 31 - 1, num),
-(2 ** 31)
);
};
console.log(
myAtoi(' 123'),
myAtoi('-456'),
myAtoi('-9999999999999'),
myAtoi('9999999999999')
);

Have a look it this solution. As we are dealing with integers, they only hold 32-bit. 2^31 < x <= -2^31. So here we use a try catch as the 32bit integer can raise NumberFormat Exception which will be caught by the catch block.
class Solution {
public int myAtoi(String str) {
int flag=0, sign = 0;
int n = str.length();
StringBuilder st = new StringBuilder();
int i =0;
//clear white spaces
while(i<n && str.charAt(i) == ' '){
++i;
}
//overflow of string
if (i>=n){
return 0;
}
//checking sign and not allowing more than one sign, will return 0 if there is ++,+-,--
while(i<n && (str.charAt(i) == '+' || str.charAt(i) == '-')){
if (sign >= 1){
return 0;
}
else{
st.append((str.charAt(i++) == '+') ? '+': '-');
sign++;
}
}
//checking if character is digit
while(i<n && Character.isDigit(str.charAt(i))){
st.append(str.charAt(i++));
flag = 1;
}
//return 0 if no digits
if(flag == 0)
return 0;
//to check if the number is within the int range
try{
return Integer.parseInt(st.toString());
}
catch(NumberFormatException e){
return (st.charAt(0) == '-') ? Integer.MIN_VALUE : Integer.MAX_VALUE;
}
}
}

Related

How do I separate a number length into single digits to then use in mathematical operation?

So I'm new to coding in Javascript, so I'm working on Code Wars and was given the problem:
{A Narcissistic Number (or Armstrong Number) is a positive number which is the sum of its own digits, each raised to the power of the number of digits in a given base. In this Kata, we will restrict ourselves to decimal (base 10).
For example, take 153 (3 digits), which is narcissistic:
1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153
and 1652 (4 digits), which isn't:
1^4 + 6^4 + 5^4 + 2^4 = 1 + 1296 + 625 + 16 = 1938
The Challenge:
Your code must return true or false (not 'true' and 'false') depending upon whether the given number is a Narcissistic number in base 10. This may be True and False in your language, e.g. PHP.}
I wrote a code that for me makes sense, and passes some of the tests, but obviously being a bit new to this I did something wrong if someone can just let me know so I can better learn and understand what to properly do for a problem like this.
function narcissistic(value) {
if (value != Number(value)) {
return "Please enter a number!"
} else {
let counter = 0;
let digits = [];
for (let i = 0; i < value.length; i++) {
if (value[i] === 0) {
value.splice[i, 1];
counter += 1;
digits.push(i);
}
}
if (value == digits ** value.length) {
return true;
} else {
return false;
}
}
return false;
}
Turn the number into a string
Establish the length of the string as the exponent
Iterate through the digits in the string, accumulating the digit operation
Return the result of an === comparison to the original value.
So:
function narc(n) {
const nstr = String(n), exp = nstr.length;
let sum = 0;
for (let i = 0; i < exp; ++i) sum += nstr[i] ** exp;
return n === sum;
}
console.log(narc(153));
console.log(narc(1652));

Script validation a number 1-100

So I need to write a script that validates a number that is great than zero and less than 100. The catch is that the number can only be accepted if there is decimal in the middle position and has at least two decimal places.
Examples: 19.30 would validate but 9.3, 9.30, and 19.3 would be considered invalid.
I'm thinking a regular expressions would be the best way to validate the decimal criteria?
Comments in the code:
function validNumber(string) {
// parse string into number
let number = parseFloat(string, 10);
// check if number is in range
if (number <= 0 || number >= 100) return false;
// check if number is formatted correctly
if (string !== number.toFixed(2)) return false;
// return true if all conditions pass
return true;
}
console.log(validNumber("19.30")); // true
console.log(validNumber("9.3")); // false
console.log(validNumber("19.3")); // false
console.log(validNumber("100.30")); // false
console.log(validNumber("1.00")); // true
What you could do is split on the decimal, then the test the lengths of the strings.
function validate(number) {
let [whole, decimal] = number.toString().split('.', 2)
let int = parseInt(whole)
return whole.length == decimal.length && decimal.length >= 2
&& int > 0 && int < 100
}
console.log(validate('19.30'))
console.log(validate('9.3'))
console.log(validate('9.30'))
console.log(validate('-9.30'))
console.log(validate('19.3'))
console.log(validate('99.99'))
console.log(validate('1.111'))
console.log(validate('100.111'))
console.log(validate('1000.111'))
The following regex meets your needs I think provided input is string along with comparison operator
\d{1,3}\.\d{2}+
You could use it as following:
const isValid = (input) => {
const num = parseFloat(input, 10);
return (!!input.match(/\d{1,3}\.\d{2}+/) && num > 0 && num < 100);
};
isValid('19.3') // => false
isValid('19.30') // => true

How to detect numeric overflow/underflow in JavaScript arithmetic operations?

I was doing a coding test today, the goal was to catch all edge cases when adding 2 integer representations of strings in JavaScript. One case I could not get was how to detect overflow/underflow for the sum stored in the IEEE 754 numeric.
Normally, in C, I'd look at the binary representation of the numeric, but in JavaScript, I can only look at 32 bits worth of the integer value.
Here's the code I had:
function string_add(a, b) {
if (arguments.length !== 2)
throw new Error('two arguments expected as input');
// ensure we have strings
if (typeof a !== 'string' || typeof b !== 'string')
throw new Error('bad parameter types');
// ensure we do not have empty strings
if (a.length === 0 || b.length === 0)
throw new Error('an empty string is an invalid argument');
// ensure we have integer arguments
if (0 !== (+a % 1) || 0 !== (+b % 1))
throw new Error('expected numeric integer strings for arguments');
var sum = +a + +b; // create numeric sum of a and b.
sum+=''; // convert numeric sum to string
return sum;
}
Thanks in advance.
Edit: JavaScript now has a Number.MAX_SAFE_INTEGER
Actually, integers in Javascript are 53 bits of information due to the way floating point math works.
The last time I needed to do something similar I did...
var MAX_INT = Math.pow(2, 53);
var MIN_INT = -MAX_INT;
var value = MAX_INT * 5;
if (value >= MAX_INT) {
alert("Overflow");
}
// Note. you have to use MAX_INT itself as the overflow mark because of this:
value = MAX_INT+1;
if (value > MAX_INT) {
alert("Overflow test failed");
}
EDIT After thinking about it, it would be easier to say:
var MAX_INT = Math.pow(2, 53) -1;
var MIN_INT = -MAX_INT;
since that is the largest INT that you know hasn't overflowed.

How to convert the last 3 digits of the number?

How to convert the last 3 digits of the number? Numbers will be bigger then 8000.
For example:
From 249439 to 249000?
You can get the last three digits using the modulus operator %, which (for positive numbers) computes the remainder after integer division; for example, 249439 % 1000 is 439.
So to round down to the nearest thousand, you can just subtract those three digits:
var rounded = original - original % 1000;
(for example, if original is 249439, then rounded will be 249000).
I'd suggest the following:
function roundLastNDigits (num, digits) {
// making sure the variables exist, and are numbers; if *not* we quit at this point:
if (!num || !parseInt(num,10) || !digits || !parseInt(digits,10)) {
return false;
}
else {
/* otherwise we:
- divide the number by 10 raised to the number of digits
(to shift divide the number so that those digits follow
the decimal point), then
- we round that number, then
- multiply by ten raised to the number of digits (to
recreate the same 'size' number/restoring the decimal fraction
to an integer 'portion' */
return Math.round(num / Math.pow(10, parseInt(digits,10))) * Math.pow(10,digits);
}
}
console.log(roundLastNDigits(249439, 3))
JS Fiddle demo.
If you'd prefer to always round down, I'd amend the above to give:
function roundLastNDigits (num, digits) {
if (!num || !parseInt(num,10) || !digits || !parseInt(digits,10)) {
return false;
}
else {
return Math.floor(num / Math.pow(10, parseInt(digits,10))) * Math.pow(10,digits);
}
}
console.log(roundLastNDigits(8501, 3))
JS Fiddle demo.
Simplifying the above by incorporating ruakh's genius approach:
function roundLastNDigits (num, digits) {
if (!num || !parseInt(num,10) || !digits || !parseInt(digits,10)) {
return false;
}
else {
return num - (num % Math.pow(10,parseInt(digits,10)));
}
}
console.log(roundLastNDigits(8501, 3))
JS Fiddle demo.
Or, finally, given that you only need to replace the last three digit characters with 0:
function roundLastNDigits (num, digits) {
if (!num || !digits || !parseInt(digits,10)) {
return false;
}
else {
var reg = new RegExp('\\d{' + digits + '}$');
return num.toString().replace(reg, function (a) {
return new Array(parseInt(digits,10) + 1).join(0);
});
}
}
console.log(roundLastNDigits(8501, 3))
JS Fiddle demo.
References:
Math.floor().
Math.pow().
Math.round().
parseInt().
For always rounding down I'd suggest dividing out 1000, casting to Int then multipling back in 1000
var x = 249439,
y = ((x / 1000) | 0) * 1000; // 249000
1)
Math.round(num.toPrecision(3));
This doesn't account for the values before the 3rd value to round.
2)
This is sort of a bad solution but it works.
num = 50343 // whatever your input is.
m = 10^n.
Math.round(num*m)/m
n being the amount you want to move over.

Converting hexadecimal to float in JavaScript

I would like to convert a number in base 10 with fraction to a number in base 16.
var myno = 28.5;
var convno = myno.toString(16);
alert(convno);
All is well there. Now I want to convert it back to decimal.
But now I cannot write:
var orgno = parseInt(convno, 16);
alert(orgno);
As it doesn't return the decimal part.
And I cannot use parseFloat, since per MDC, the syntax of parseFloat is
parseFloat(str);
It wouldn't have been a problem if I had to convert back to int, since parseInt's syntax is
parseInt(str [, radix]);
So what is an alternative for this?
Disclaimer: I thought it was a trivial question, but googling didn't give me any answers.
This question made me ask the above question.
Another possibility is to parse the digits separately, splitting the string up in two and treating both parts as ints during the conversion and then add them back together.
function parseFloat(str, radix)
{
var parts = str.split(".");
if ( parts.length > 1 )
{
return parseInt(parts[0], radix) + parseInt(parts[1], radix) / Math.pow(radix, parts[1].length);
}
return parseInt(parts[0], radix);
}
var myno = 28.4382;
var convno = myno.toString(16);
var f = parseFloat(convno, 16);
console.log(myno + " -> " + convno + " -> " + f);
Try this.
The string may be raw data (simple text) with four characters (0 - 255) or
a hex string "0xFFFFFFFF" four bytes in length.
jsfiddle.net
var str = '0x3F160008';
function parseFloat(str) {
var float = 0, sign, order, mantissa, exp,
int = 0, multi = 1;
if (/^0x/.exec(str)) {
int = parseInt(str, 16);
}
else {
for (var i = str.length -1; i >=0; i -= 1) {
if (str.charCodeAt(i) > 255) {
console.log('Wrong string parameter');
return false;
}
int += str.charCodeAt(i) * multi;
multi *= 256;
}
}
sign = (int >>> 31) ? -1 : 1;
exp = (int >>> 23 & 0xff) - 127;
mantissa = ((int & 0x7fffff) + 0x800000).toString(2);
for (i=0; i<mantissa.length; i+=1) {
float += parseInt(mantissa[i]) ? Math.pow(2, exp) : 0;
exp--;
}
return float*sign;
}
Please try this:
function hex2dec(hex) {
hex = hex.split(/\./);
var len = hex[1].length;
hex[1] = parseInt(hex[1], 16);
hex[1] *= Math.pow(16, -len);
return parseInt(hex[0], 16) + hex[1];
}
function hex2dec(hex) {
hex = hex.split(/\./);
var len = hex[1].length;
hex[1] = parseInt(hex[1], 16);
hex[1] *= Math.pow(16, -len);
return parseInt(hex[0], 16) + hex[1];
}
// ----------
// TEST
// ----------
function calc(hex) {
let dec = hex2dec(hex);
msg.innerHTML = `dec: <b>${dec}</b><br>hex test: <b>${dec.toString(16)}</b>`
}
let init="bad.a55";
inp.value=init;
calc(init);
<input oninput="calc(this.value)" id="inp" /><div id="msg"></div>
I combined Mark's and Kent's answers to make an overloaded parseFloat function that takes an argument for the radix (much simpler and more versatile):
function parseFloat(string, radix)
{
// Split the string at the decimal point
string = string.split(/\./);
// If there is nothing before the decimal point, make it 0
if (string[0] == '') {
string[0] = "0";
}
// If there was a decimal point & something after it
if (string.length > 1 && string[1] != '') {
var fractionLength = string[1].length;
string[1] = parseInt(string[1], radix);
string[1] *= Math.pow(radix, -fractionLength);
return parseInt(string[0], radix) + string[1];
}
// If there wasn't a decimal point or there was but nothing was after it
return parseInt(string[0], radix);
}
Try this:
Decide how many digits of precision you need after the decimal point.
Multiply your original number by that power of 16 (e.g. 256 if you want two digits).
Convert it as an integer.
Put the decimal point in manually according to what you decided in step 1.
Reverse the steps to convert back.
Take out the decimal point, remembering where it was.
Convert the hex to decimal in integer form.
Divide the result by the the appropriate power of 16 (16^n, where n is the number of digits after the decimal point you took out in step 1).
A simple example:
Convert decimal 23.5 into hex, and want one digit after the decimal point after conversion.
23.5 x 16 = 376.
Converted to hex = 0x178.
Answer in base 16: 17.8
Now convert back to decimal:
Take out the decimal point: 0x178
Convert to decimal: 376
Divide by 16: 23.5
I'm not sure what hexadecimal format you wanted to parse there. Was this something like: "a1.2c"?
Floats are commonly stored in hexadecimal format using the IEEE 754 standard. That standard doesn't use any dots (which don't exist in pure hexadecimal alphabet). Instead of that there are three groups of bits of predefined length (1 + 8 + 23 = 32 bits in total ─ double uses 64 bits).
I've written the following function for parsing such a numbers into float:
function hex2float(num) {
var sign = (num & 0x80000000) ? -1 : 1;
var exponent = ((num >> 23) & 0xff) - 127;
var mantissa = 1 + ((num & 0x7fffff) / 0x7fffff);
return sign * mantissa * Math.pow(2, exponent);
}
Here is a size-improvement of Mark Eirich's answer:
function hex2dec(hex) {
let h = hex.split(/\./);
return ('0x'+h[1])*(16**-h[1].length)+ +('0x'+h[0]);
}
function hex2dec(hex) {
let h = hex.split(/\./);
return ('0x'+h[1])*(16**-h[1].length)+ +('0x'+h[0]);
}
function calc(hex) {
let dec = hex2dec(hex);
msg.innerHTML = `dec: <b>${dec}</b><br>hex test: <b>${dec.toString(16)}</b>`
}
let init = "bad.a55";
inp.value = init;
calc(init);
<input oninput="calc(this.value)" id="inp" /><div id="msg"></div>
private hexStringToFloat(hexString: string): number {
return Buffer.from(hexString, 'hex').readFloatBE(0);
}
Someone might find this useful.
bytes to Float32
function Int2Float32(bytes) {
var sign = (bytes & 0x80000000) ? -1 : 1;
var exponent = ((bytes >> 23) & 0xFF) - 127;
var significand = (bytes & ~(-1 << 23));
if (exponent == 128)
return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY);
if (exponent == -127) {
if (significand === 0) return sign * 0.0;
exponent = -126;
significand /= (1 << 22);
} else significand = (significand | (1 << 23)) / (1 << 23);
return sign * significand * Math.pow(2, exponent);
}

Categories

Resources