Is there a way to distinguish integers from very near decimals in Javascript? - javascript

Look at those evaluations (actual dump from node 0.10.33)
> parseFloat(2.1e-17) === parseInt(2.1e-17)
false
> parseFloat(2.1e-17 + 2) === parseInt(2.1e-17 + 2)
true
> parseFloat(2.000000000000000000000000000000000009) === parseInt(2.00000000000000000000000000000000000009)
true
How can I tell integers from decimals very near to integers?
It seems that JS (or at least V8) doesn't care about digits smaller than 10^-16 when doing calculations, even if the 64bit representation used by the language (reference) should handle it.

Your examples are pretty much straight forward to explain. First thing to note is, that parseInt() and parseFloat() take a string as an input. So you inputs first get converted to string, before actually getting parsed.
The first is easy to see:
> parseFloat(2.1e-17) === parseInt(2.1e-17)
false
// look at the result of each side
parseFloat(2.1e-17) == 2.1e-17
parseInt(2.1e-17) == 2
When parsing the string "2.1e-17" as integer, the parse will stop at the dot as that is no valid digit and return everything it found until then, which is just 2.
> parseFloat(2.1e-17 + 2) === parseInt(2.1e-17 + 2)
true
// look at the result of each side
parseFloat(2.1e-17 + 2) == 2
parseInt(2.1e-17 + 2) == 2
Here the formula in the parameter will be evaluated first. Due to the limitations of floating point math (we just have 52bit for the mantissa and can't represent something like 2.000000000000000021), this will result in just 2. So both parseX() function get the same integer parameter, which will result in the same parsed number.
> parseFloat(2.000000000000000000000000000000000009) === parseInt(2.00000000000000000000000000000000000009)
true
Same argument as for the second case. The only difference is, that instead of a formula, that gets evaluated, this time it is the JavaScript parser, which converts your numbers just to 2.
So to sum up: From JavaScript's point of view, your numbers are just the same. If you need more precision, you will have to use some library for arbitrary precision.

This is something I learned from ReSharper
instead of using expressions like
if (2.00001 == 2) {}
try
if (Math.abs(2.00001 - 2) < tolerance) {}
where tolerance should be an aceptable value for you for example .001
so all values wich difference is less than .001 will be equals
Do you really need 10^-16 precision I mean that is why 1000 meter = 1 kilometer, just change the unit of the output so you dont have to work with all those decimals

Related

JS Regex says Number contains a '.' but there is none

On this page, https://emperorbob7.github.io/JSheets/, I have a function called TYPE, syntax for it is linked on the page, the RegEx used for the decimal detection function is located in codeblock below*
Once I put in too many numbers however, the TYPE says the cell contains a decimal despite none being there. Is this an automatic function that adds a . whenever a number exceeds a certain limit?
Example case: 3123123123123123123122312312312
Output: Decimal
Edit:
function TYPE() {
const regex = /\.[0-9]/;
if(arguments[0] == "true" || arguments[0] == "false")
return "Boolean";
if(isNaN(arguments[0]))
return "String";
else if(regex.test(arguments[0]))
return "Decimal";
else
return "Integer";
}
Code^ Sorry for not posting it before, will keep it in mind for the future.
Sorry for the badly worded question, thanks in advance
You have an integer that is larger than the Number object can handle (see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER), so when it's converted to a string for the regex it becomes an exponential value.
Try console.log(3123123123123123123122312312312); and you will get 3.123123123123123e+30
Or
let val = 3123123123123123123122312312312;
val.toString();
"3.123123123123123e+30"
You can also test your value with Number.isSafeInteger(3123123123123123123122312312312);, which returns false.
The solution is to use Number.isInteger(); as your test instead of a regex. It correctly returns true for your large number.
See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
Javascript can only store integers up to 9007199254740991 safely. Beyond that, javascript may convert the number to power notation (i.e., 5000000000000000000000 becomes 5e+21) or start converting digits into zeros for storage.
var n = 3123123123123123123122312312312;
console.log(n);
/* Output: 3.123123123123123e+30 */
You can use Number.isSafeInteger() to test whether the number is within the safe range, and then apply your original code to it in that case. If not, you can perform a different test (such as a test against /\d\.\d+e\+\d+ ) to see whether the decimal included is due to exponent notation.
Also be aware that a number in exponent notation will test true using Number.isInteger(), even if it was a floating point to begin with, as that information will be lost.
var x_int = 3123123123123123123122312312312;
var x_flt = 3123123123123123123122312312312.333333333;
console.log( x_int === x_flt);
/* Output: true */
console.log(Number.isInteger(x_flt));
/* Output: true */

Converting a Two's complement number to its binary representation

I am performing bitwise operations, the result of which is apparently being stored as a two's complement number. When I hover over the variable it's stored in I see- num = -2086528968.
The binary of that number that I want is - (10000011101000100001100000111000).
But when I say num.toString(2) I get a completely different binary representation, the raw number's binary instead of the 2s comp(-1111100010111011110011111001000).
How do I get the first string back?
Link to a converter: rapidtables.com/convert/number/decimal-to-binary.html
Put in this number: -2086528968
Follow bellow the result:
var number = -2086528968;
var bin = (number >>> 0).toString(2)
//10000011101000100001100000111000
console.log(bin)
pedro already answered this, but since this is a hack and not entirely intuitive I'll explain it.
I am performing bitwise operations, the result of which is apparently being stored as a two's complement number. When I hover over the variable its stored in I see num = -2086528968
No, the result of most bit-operations is a 32bit signed integer. This means that the bit 0x80000000 is interpreted as a sign followed by 31 bits of value.
The weird bit-sequence is because of how JS stringifies the value, something like sign + Math.abs(value).toString(base);
How to deal with that? We need to tell JS to not interpret that bit as sign, but as part of the value. But how?
An easy to understand solution would be to add 0x100000000 to the negative numbers and therefore get their positive couterparts.
function print(value) {
if (value < 0) {
value += 0x100000000;
}
console.log(value.toString(2).padStart(32, 0));
}
print(-2086528968);
Another way would be to convert the lower and the upper bits seperately
function print(value) {
var signBit = value < 0 ? "1" : "0";
var valueBits = (value & 0x7FFFFFFF).toString(2);
console.log(signBit + valueBits.padStart(31, 0));
}
print(-2086528968);
//or lower and upper half of the bits:
function print2(value) {
var upperHalf = (value >> 16 & 0xFFFF).toString(2);
var lowerHalf = (value & 0xFFFF).toString(2);
console.log(upperHalf.padStart(16, 0) + lowerHalf.padStart(16, 0));
}
print2(-2086528968);
Another way involves the "hack" that pedro uses. You remember how I said that most bit-operations return an int32? There is one operation that actually returns an unsigned (32bit) interger, the so called Zero-fill right shift.
So number >>> 0 does not change the bits of the number, but the first bit is no longer interpreted as sign.
function uint32(value){
return value>>>0;
}
function print(value){
console.log(uint32(value).toString(2).padStart(32, 0));
}
print(-2086528968);
will I run this shifting code only when the number is negative, or always?
generally speaking, there is no harm in running nr >>> 0 over positive integers, but be careful not to overdo it.
Technically JS only supports Numbers, that are double values (64bit floating point values). Internally the engines also use int32 values; where possible. But no uint32 values. So when you convert your negative int32 into an uint32, the engine converts it to a double. And if you follow up with another bit operation, first thing it does is converting it back.
So it's fine to do this like when you need an actual uint32 value, like to print the bits here, but you should avoid this conversion between operations. Like "just to fix it".

how to set automatically decimal values using javascript

I want to change the number into integer and decimal portions after specific length. For example if I am entering more than 8 digit balance digits should be displayed as decimal values.
input :
4567454857
output:
45674548.57
Javascript Numbers without a decimal portion (ie, they look like ints) can be easily converted to decimals through division (JS isn't like other languages where ints can't become floats). However, for your problem, I have a solution involving substrings and the ability to convert freely between Number and String.
function truncateToEightDigits(num) {
if (num > 99999999) { // if num has more than 8 digits
var str = String(num);
return Number(str.substr(0, 8) + '.' + str.substr(8, str.length));
} else {
return num;
}
}
This also has the added benefit of avoiding weird issues with floating point math you might incur if you tried to do something such as divide by 10 repeatedly.
Side note: I'm not really sure what this has to do with ASP.NET and I'm kinda wondering why you tagged your question with that.

Can someone please explain this JavaScript decimal rounding function in detail?

function Round2DecimalPlaces(l_amt) {
var l_dblRounded = +(Math.round(l_amt + "e+2") + "e-2");
return l_dblRounded;
}
Fiddle: http://jsfiddle.net/1jf3ut3v/
I'm mainly confused on how Math.round works with "e+2" and how addition the "+" sign to the beginning of Math.round makes any difference at all.
I understand the basic of the function; the decimal gets moved n places to the right (as specified by e+2), rounded with this new integer, and then moved back. However, I'm not sure what 'e' is doing in this situation.
eX is a valid part of a Number literal and means *10^X, just like in scientific notation:
> 1e1 // 1 * Math.pow(10, 1)
10
> 1e2 // 1 * Math.pow(10, 2)
100
And because of that, converting a string containing such a character sequence results in a valid number:
> var x = 2;
> Number(x + "e1")
20
> Number(x + "e2")
200
For more information, have a look at the MDN JavaScript Guide.
But of course the way this notation is used in your example is horrible. Converting values back and forth to numbers and strings is already bad enough, but it also makes it more difficult to understand.
Simple multiple or divide by a multiple of 10.
The single plus operator coerces a the string into a float. (See also: Single plus operator in javascript )

Bitwise check in Javascript

I play a game, and in the database we set 100663296 to be a GM Leader but also this field in the database gets written to for different things, so it changes that number to 100794368
i was told to possible use a bit-wise check to check whether the first number is the same as the second number, and I have googled on using bit-wise checks but got confused as to what to use for my check.
Here are some other numbers that change, including the one from above.
predefined number new changed number/ever changing number.
100663296 = 100794368
67108864 = 67239936
117440512 = 2231767040
so how should i go about checking these numbers?
And here is part of my code that i was using before i noticed the change in the numbers.
if (playerData[i].nameflags == 67108864)
{
playerRows += '<img src ="icons/GM-Icon.png" alt="GM" title="GM"></img>';
}
thx to Bergi, for the answer.
if (playerData[i].nameflags & 0x400000 /* === 0x400000 */)
this seams to work great.
also thx to vr1911428
and every one else for the help on this.
So let's convert those numbers to binary representation (unsigned integer):
> 100663296
00000110000000000000000000000000
> 100794368
00000110000000100000000000000000
> 67108864
00000100000000000000000000000000
> 67239936
00000100000000100000000000000000
> 117440512
00000111000000000000000000000000
> 2231767040
10000101000001100001000000000000
Notice that the last number is out of the scope of JavaScripts bitwise arithmetic, which only works with 32-bit signed integers - you won't be able to use the leftmost bit.
So which bits do you want to compare now? There are lots of possibilities, the above scheme doesn't make it clear, yet it looks like you are looking for the 27th bit from the right (226 = 67108864). To match against it, you can apply a binary AND bitmask:
x & Math.pow(2, 26)
which should evaluate to 226 again or zero - so you can just check for truthiness. Btw, instead of using pow you could use hexadecimal notation: 0x4000000. With that, your condition will look like this:
if (playerData[i].nameflags & 0x400000 /* === 0x400000 */)
If you need to check for full bitwise equality of two integers, all you need is just '==' operator, but to use it, you should guarantee that both operands are integers:
left = 12323;
right = 12323;
if (left == right)
alert("Operands are binary equal; I'll guarantee that. :-)");
Be very careful though; if at least one of operands is string representing number, not a number, both operands will be considered strings and you can get confusing results:
left = "012323";
right = 12323;
if (left != right)
alert("Operands are not equal, even though they represent 'equal values', as they are compared as strings.");
In general, these days, the attempt to operate with strings representing data instead of data itself is a real curse of the beginners; and it's hard to explain to them. It is especially difficult to explain in JavaScript, with its loose-type typing concept, which is itself very complex and hard to understand, behind the illusory simplicity.
Finally, if you need to compare separate bits (and, from your question, I don't see this need), you can use binary operators:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators
That's it, basically.
...................

Categories

Resources