Comparing negative numbers in javascript - javascript

I'm sure this is a simple problem, but I'm comparing negative numbers in javascript i.e.:
var num1 = -83.778;
var num2 = -83.356;
if(num1 < num2)
{
// Take action 1
}
else
{
// Take action 2
}
This script will always take action 2, even though num1 is less than num2. Whats going on here?

How does if (parseFloat(num1) < parseFloat(num2)) work? Maybe your numbers are turning into strings somewhere.

This case also works when we want to compare signed characters for both positive and negative numbers. For my case i had numbers like +3, +4, 0, -1 etc..
Directly using if(num1 > num2) would compare these values as string and we would get output of string comparision.
Thus to compare signed numbers., compare them via if (parseFloat(num1) < parseFloat(num2))

I have the same issue. Workaround for that:
var num1 = -83.778;
var num2 = -83.356;
if((num1 - num2) < 0)
{
// Take action 1
}
else
{
// Take action 2
}
Now Ation 1 will be used.

Related

Javascript - Max 4 Digits after Comma

I`m looking for a way to delete the last Digits from an Input with comma if the Value is more then 4.
Example:
Value : 13,314556 should be -> 13,3145.
Is there a way to just remove everything then the last 4 digits of this number with something like this?
let value = 13,314556
let result= value.split(',')[1].trim();
if(result.length > 4){
...
}
toFixed()
You can call toFixed() to format the number to a number of decimal places.
See MDN Documentation for toFixed()
Modified from the example given in the above documentation:
function myFormat(x) {
return Number.parseFloat(x).toFixed(4);
}
// expected output: "13.3146" because of rounding
console.log(myFormat(13.314556));
// expected output: "0.0040"
console.log(myFormat(0.004));
// expected output: "123000.0000"
console.log(myFormat('1.23e+5'));
If you don't want rounding, simply be more precise and clip the end of the resulting string.
function myFormat(x) {
return Number.parseFloat(x).toFixed(6).replace(/\d\d$/, '');
}
// expected output: "13.3145", will not do rounding
console.log(myFormat(13.314556));
If you are working with currency or do similar important calculations, consider working with a library like decimal.js.
alternative is to multiply by 10000, floor it, then divide by 10000.
let value = 13.314556;
value=Math.floor(value*10000)/10000;
console.log(value)
or if you want to control the number of digits programmatically you could use something like this:
let value = 13.314556;
value=Math.floor(value*Math.pow(10, 4))/Math.pow(10, 4);
console.log(value)
Maybe you are looking for slice function.
let value = "13,314556"
let result= value.split(',')[1].trim();
if(result.length > 4){
console.log(result.split('').slice(0,4).join(''))
}
I would do it with the slice and
join methods
Slice for slicing the string with the length you want
Join to re-create the number as you wish
Edit
I added check if comma is in the number and also a parameter with the desired length
function splitNumber(num, nbAfterComa) {
const number = num.toString()
if(!number.includes('.')){
return number
}
const splitedValue = number.split('.')
splitedValue[1] = splitedValue[1].trim().slice(0, nbAfterComa);
return nbAfterComa > 0 ? splitedValue.join(',') : splitedValue[0]
}
console.log(splitNumber(13.314556, 4))
console.log(splitNumber(13.3, 4))
console.log(splitNumber(13.314556, 1))
console.log(splitNumber(13.314556, 0))
console.log(splitNumber(13, 8))

JavaScript - wrong float values comparison

There are two fields - faceValue fv2 and askingPrice num2 - and askingPrice can't be less than faceValue.
The check is almost working, but with a face value of 10.00, the alert only triggers when the asking price is 1.00 (9.00, 8.00 etc etc don't trigger it). However, when fv2 reloads into the form it's correct - 10.00.
How to fix this issue? here's the code
// new askingPrice comparison
var fv2 = parseFloat($('.ticketFaceValue').val()).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
var num2 = parseFloat($(this).val()).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
if (num2 < fv2) {
alert('Sorry, your asking price can\'t be less than face value. Please change your asking price.');
$(this).val(fv2);
row.find('.askingPriceData').html(fv2);
recalculateFees();
}
// end new askingPrice comparison
Although you use parseFloat to convert the input string to a number type, you convert it back to string with toFixed, and so the comparison is character based, not by numerical value.
The thing you try to do with a replace (add thousands separators) can also be done with toLocaleString, but you need to take care to not to put that formatted string back into the input element, as it will not parse as a number. It is probably better to use separate variables for the numerical value and the formatted value. Maybe like this:
var fv2 = +$('.ticketFaceValue').val()
var num2 = +$(this).val();
var fv2Fmt =fv2.toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2});
var num2Fmt =num2.toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2});
if (num2 < fv2) {
alert('Sorry, your asking price can\'t be less than face value. Please change your asking price.');
$(this).val(fv2);
row.find('.askingPriceData').html(fv2Fmt);
recalculateFees();
}
toFixed() method returns string so you are comparing two strings. Try the below code.
var fv2_float = parseFloat($('.ticketFaceValue').val());
var num2_float = parseFloat($(this).val());
var fv2 = fv2_float.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
var num2 = num2_float.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
if (num2_float < fv2_float) {
// Do your staff
}
Or try below one, but this is not very efficient.
// Your code goes here
if (parseFloat(num2) < parseFloat(fv2)) {
// Do your staff
}

Javascript Comparison operator string and number

I am practicing the comparison operators in an if/else statement. My question is that I am expecting the window will give me a True alert, but instead it gave me the False alert. I thought the system will coerce num1 into 97 before it performs the comparison.
Here is my code:
var num1 = "a";
var num2 = 99999;
if (num1 <= num2) {
window.alert("True");
}else {
window.alert("False");
}
I believe the answer to your question has to do with implicit conversions which are happening here. Consider the following line of code:
console.log(99999 + "a")
This will output 99999a, and it won't convert the "a" string to a number. Assuming the same happens with your code snippet, it explains the observations. What we are seeing is consistent with this:
var num1 = "a";
var num2 = "99999";
if (num1 <= num2) {
console.log("True");
} else {
console.log("False");
}
The reason why this is false is that the letter a is lexicographically greater than any single digit character. And since JavaScript is comparing two strings, they are sorting as text, and the first character is all which needs to be examined to render an ordering.
You can use .codePointAt() to get the code point of the charcter
var num1 = "a";
var num2 = 99999;
if (num1.codePointAt(0) <= num2) {
window.alert("True");
} else {
window.alert("False");
}
the above condition is translated as
if(parseInt(num1)<= parseInt(num2)) {
//something
}
parseInt(num1) returns NaN (Not a number) and NaN is, by definition, not less than, equal to, or greater than any other number.
Hence the output is false.
num1="a" is a string and in the comparison num1<=num2, num2 is a number.
Implicit conversion happens here and num2 is converted into a string.
There are several ways to convert a string(of type "345", etc) into a number:
Number()
parseInt()
parseFloat()
bitwise ~~
But the string num1 contains a character so these functions return NaN(Not a number).Hence we cannot convert the string of characters into a number.
Your purpose can be achieved using the charCodeAt() function as follows :
var num1="a";
var num2=9999;
if(num1.charCodeAt(0)<=num2){
window.alert("True");
}else{
window.alert("False");
}

Javascript: parsing negative Number(hexadecimal | binary)

It works with a lot number types, but not with negatives hexadecimal or binary.
Too, Number(octal) doesn't parse an octal number.
Number("15") === 15; // OK
Number("-15") === -15; // OK
Number("0x10") === 16; // OK
Number("0b10") === 2; // OK
Number("-0x10") === NaN; // FAIL (expect -16)
Number("-0b10") === NaN; // FAIL (expect -2)
Number("0777") === 777; // FAIL (expect 511)
Number("-0777") === -777; // FAIL (expect -511)
Question: how I can parse all valid Javascript numbers correctly?
Edit A
parseInt() don't help me because I need check by each possibility (if start with 0x I use 16, for instance).
Edit B
If I write on Chrome console 0777 it turns to 511, and too allow negative values. Even works if I write directly into javascript code. So I expect basically a parser that works like javascript parser. But I think that the negative hexadecimal, for instance, on really is 0 - Number(hex) in the parser, and not literraly Number(-hex). But octal values make not sense.
Try this:
parseInt(string, base):
parseInt("-0777", 8)
parseInt("-0x10", 16)
You could write a function to handle the negative value.
function parseNumber (num) {
var neg = num.search('-') > -1;
var num = Number(num.replace('-', ''));
return num * (neg ? -1 : 1);
}
It's not parsing octal and the other examples because they're not valid Javascript numbers, at least within the constraints of Number. So the technically correct answer is: use Number!
If you want to parse other formats, then you can use parseInt, but you will have to provide the base.
This gets a little ugly, but you could inspect the values to determine the right radix for parseInt. In particular, the b for binary doesn't seem to be support by my browser (Chrome) at all, so unlike the OP, Number("0b10") gives me NaN. So you need to remove the b for it to work at all.
var numbers = [
"15", "-15", "0x10", "0b10", "-0x10", "-0b10", "0777", "-0777"
];
function parser(val) {
if (val.indexOf("x") > 0) {
// if we see an x we assume it's hex
return parseInt(val, 16);
} else if (val.indexOf("b") > 0) {
// if we see a b we assume it's binary
return parseInt(val.replace("b",""),2);
} else if (val[0] === "0") {
// if it has a leading 0, assume it's octal
return parseInt(val, 8);
}
// anything else, we assume is decimal
return parseInt(val, 10);
}
for (var i = 0; i < numbers.length; i++) {
console.log(parser(numbers[i]));
}
Note this obviously isn't foolproof (for example, I'm checking for x but not X), but you can make it more robust if you need to.

Math.random() returns value greater than one?

While playing around with random numbers in JavaScript I discovered a surprising bug, presumably in the V8 JavaScript engine in Google Chrome. Consider:
// Generate a random number [1,5].
var rand5 = function() {
return parseInt(Math.random() * 5) + 1;
};
// Return a sample distribution over MAX times.
var testRand5 = function(dist, max) {
if (!dist) { dist = {}; }
if (!max) { max = 5000000; }
for (var i=0; i<max; i++) {
var r = rand5();
dist[r] = (dist[r] || 0) + 1;
}
return dist;
};
Now when I run testRand5() I get the following results (of course, differing slightly with each run, you might need to set "max" to a higher value to reveal the bug):
var d = testRand5();
d = {
1: 1002797,
2: 998803,
3: 999541,
4: 1000851,
5: 998007,
10: 1 // XXX: Math.random() returned 4.5?!
}
Interestingly, I see comparable results in node.js, leading me to believe it's not specific to Chrome. Sometimes there are different or multiple mystery values (7, 9, etc).
Can anyone explain why I might be getting the results I see? I'm guessing it has something to do with using parseInt (instead of Math.floor()) but I'm still not sure why it could happen.
The edge case occurs when you happen to generate a very small number, expressed with an exponent, like this for example 9.546056389808655e-8.
Combined with parseInt, which interprets the argument as a string, hell breaks loose. And as suggested before me, it can be solved using Math.floor.
Try it yourself with this piece of code:
var test = 9.546056389808655e-8;
console.log(test); // prints 9.546056389808655e-8
console.log(parseInt(test)); // prints 9 - oh noes!
console.log(Math.floor(test)) // prints 0 - this is better
Of course, it's a parseInt() gotcha. It converts its argument to a string first, and that can force scientific notation which will cause parseInt to do something like this:
var x = 0.000000004;
(x).toString(); // => "4e-9"
parseInt(x); // => 4
Silly me...
I would suggest changing your random number function to this:
var rand5 = function() {
return(Math.floor(Math.random() * 5) + 1);
};
This will reliably generate an integer value between 1 and 5 inclusive.
You can see your test function in action here: http://jsfiddle.net/jfriend00/FCzjF/.
In this case, parseInt isn't the best choice because it's going to convert your float to a string which can be a number of different formats (including scientific notation) and then try to parse an integer out of it. Much better to just operate on the float directly with Math.floor().

Categories