javascript really strange behaviour - javascript

I have the following code
if (msg.position == 0)
//removed for brevity
else if (msg.position == txtArea.value.length)
//removed for brevity
else {
//ERROR: should not reach here.
errorDivTag.innerHTML += msg.position + " " + txtArea.value.length;
}
I'm having some really weird situations where I'm getting the error in the last code block, but the printed positions show that msg.position is in fact equal to the txtArea.value.length. This only happens 1% of the time, almost as if I have some kind of race-condition in my code where the two are NOT equal during the second if statement, but equal when I print in the error message.
Any ideas?

If you use
parseInt(msg.position)
without a radix, you will run into problems with 08 and 09, because they are parsed as octal numbers and giving NaN. Always use a radix:
parseInt(msg.position, 10)

To start with, always use ===. That will prevent JavaScript from automatically coercing the types in the comparison, which means you'll be able to spot all sorts of bugs much more easily. In this case, it's possible you have some whitespace (which is basically impossible to see in the output) that is causing a string comparison instead of the (I assume) desired numeric comparison.
Also, I'm assuming you really meant to have { after your if and else if conditions. If not, that could be causing all sorts of strange behavior, depending on the code you removed due to brevity concerns. If you didn't, then you've got an extraneous } before your else condition.
UPDATE: Set a breakpoint in Firebug/DeveloperTools/DragonFly/whatever and inspect the values as the comparison occurs.

Did you try changing the statement to...
parseInt(msg.position, 10) == txtArea.value.length

=== is more strict than == and is often useful. But this is the opposite problem as what you have here, where something looks equal, but isn't == or === (if something isn't ==, it will never be ===).
Is msg.position a String? Perhaps it contains a space or another similar character.

I had this problem today with a checksum value in one of my js modules. A test was showing that two values were not equal, yet printing the values showed they were equal.
Ran it in the debugger and (re-)discovered that integer types in Javascript are 64-bit floating quantities. One of the numbers was displaying as negative in the debugger - exactly (0xFFFFFFFF+1) less than the other number. Somehow when printed, they displayed as exactly the same.
I was using a custom routine to format them in hex, which probably had something to do with it. That combination of circumstances seems unlikely in your case though.
I discovered the sign issue in my code by computing the delta between the numbers, and displaying that. It showed up as MAX_UINT32 + 1, which reminded me that these numbers are really 64-bit floats.

Related

Javascript toFixed() is not working as expected

I am using toFixed but the method does not operate as expected
parseFloat(19373.315).toFixed(2);
//19373.31 Chrome
Expected Output : 19373.32
parseFloat(9373.315).toFixed(2);
// 9373.32 Working fine
Why does the first example round down, whereas the second example round up?
The problem is that binary floating point representation of most decimal fractions is not exact. The internal representation of 19373.315 may actually be something like 19373.314999999, so toFixed rounds down, while 19373.315 might be 19373.315000001, which rounds up.
Why does the first example round down, whereas the second example round up?
Look at the binary representation of the two values in memory.
const farr = new Float64Array(2);
farr[0] = 19373.315;
farr[1] = 9373.315;
const uarr = new Uint32Array(farr.buffer);
console.log(farr[0], uarr[1].toString(2).padStart(32, 0) + uarr[0].toString(2).padStart(32, 0));
console.log(farr[1], uarr[3].toString(2).padStart(32, 0) + uarr[2].toString(2).padStart(32, 0));
Without diving into the details, we can see that the second value has an additional '1' at the end, which is lost in the first larger value when it is fit into 64 bits.
Other answers have explained why, I would suggest using a library like numeral.js which will round things as you would expect.
Assuming toFixed casts to 32-bit float;
Check with this utility...
19373.315 is stored as 19373.314453125 (an error of -0.000546875) in 32-bit floating point format.
This is despite (19373.315).toFixed(4) coming out as 19373.3150.
Even if this is "expected" or "intended", I'd still report it as a bug.
It should use a double during the rounding check, and thus proper rounding during conversion to fixed string.
I think the spec even says so. :\
In the V8 javascript engine source, the Number.prototype.toFixed function invokes DoubleToFixedCString in this file ...
There's probably some inappropriate optimization in there... (Looking into it.)
I'd suggest submitting an additional test case for V8 with 19373.315 specifically.
(19373.3150).toFixed(39) yields 19373.314999999998690327629446983337402343750.
Rounding occurs once to bring it up to 19373.315 - which is correct - but not at the right digit when rounding to 2 digits.
I think this should have a second pass on rounding here to catch edge cases like this. I think it might have to round to n+1 digits, then again to n digits. Maybe there's some other clever way to fix it though.
function toFixedFixed(a,n) {
return (a|0) + parseFloat((a % 1).toFixed(n+1)).toFixed(n).substr(1);
}
console.log(toFixedFixed(19373.315,2)); // "19373.32"
console.log(toFixedFixed(19373.315,3)); // "19373.315"
console.log(toFixedFixed(19373.315,4)); // "19373.3150"
console.log(toFixedFixed(19373.315,37)); // "19373.3149999999986903276294469833374023438"
console.log(toFixedFixed(19373.315,38)); // "19373.31499999999869032762944698333740234375"
console.log(toFixedFixed(19373.315,39)); // "19373.314999999998690327629446983337402343750"
(Adopted from my comments on Vahid Rahmani's answer, who is correct.)

how to have one decimal point for numbers using angularJS

i've seen a few things for regExp but for some reason i'm thinking this should be more simple. Maybe not. Maybe regExp fits this perfectly and i don't understand the concept. Which, i do not. I don't understand regExp and thats why i haven't used it.
but what i am trying to do is build a basic calculator using AngularJS. My calculator has an ng-disable feature for my equals sign. So its not allowed to be pressed and won't work until a leftOperand, operator, and rightOperand are clicked.
Now i don't want to disable the decimal when its clicked, because i might need it for my rightOperand.
But in essence i want my code to reflect "if there is an operator, then the rightOperand is rightOperand + any other Operand entered. Otherwise, the leftOperand is going to equal the leftOperand + any other Operand Entered. (which this is currently working ex. 333 + 45948594 works. The decimal works too. But! it can allow 333.464.6454 and i don't want that).
Trying to implement:
Also/And/Or/If a decimal is put into the leftOperand, then no other decimals are allowed for the leftOperand. If the rightOperand has a decimal, then no other decimals are allowed for the rightOperand.
what is the simplest way to go about this?
https://codepen.io/tevon/pen/Moewba
this is my setDecimal method, but its allowing more than 1 decimal for both the right and left operands
$scope.setDecimal = function (decimalEntered) {
if ($scope.operator){
$scope.rightOperand += decimalEntered;
};
else {$scope.leftOperand += decimalEntered;
};
i was givin something like this: if string.indexOf('.') > -1 // then do something
but honestly, i'm not sure how to about the 'do something' part works, nor the -1 portion
not using Jquery.
So you're building your operand as a string. That means you can test the operand you currently have on your scope to see if it has a point using .indexOf.
if (myVariable.indexOf('.') === -1) myVariable += '.';
You were right when you thought about indexOf - you just need to stop execution of this method if there's already dot there - and easiest way is return
if ($scope.rightOperand.indexOf('.')>-1) return;
LINK

Why does Number('') returns 0 whereas parseInt('') returns NaN

I have gone through similar questions and answers on StackOverflow and found this:
parseInt("123hui")
returns 123
Number("123hui")
returns NaN
As, parseInt() parses up to the first non-digit and returns whatever it had parsed and Number() tries to convert the entire string into a number, why unlikely behaviour in case of parseInt('') and Number('').
I feel ideally parseInt should return NaNjust like it does with Number("123hui")
Now my next question:
As 0 == '' returns true I believe it interprets like 0 == Number('') which is true. So does the compiler really treat it like 0 == Number('') and not like 0 == parseInt('') or am I missing some points?
The difference is due in part to Number() making use of additional logic for type coercion. Included in the rules it follows for that is:
A StringNumericLiteral that is empty or contains only white space is converted to +0.
Whereas parseInt() is defined to simply find and evaluate numeric characters in the input, based on the given or detected radix. And, it was defined to expect at least one valid character.
13) If S contains a code unit that is not a radix-R digit, let Z be the substring of S consisting of all code units before the first such code unit; otherwise, let Z be S.
14) If Z is empty, return NaN.
Note: 'S' is the input string after any leading whitespace is removed.
As 0=='' returns true I believe it interprets like 0==Number('') [...]
The rules that == uses are defined as Abstract Equality.
And, you're right about the coercion/conversion that's used. The relevant step is #6:
If Type(x) is Number and Type(y) is String,
return the result of the comparison x == ToNumber(y).
To answer your question about 0==''returning true :
Below is the comparison of a number and string:
The Equals Operator (==)
Type (x) Type(y) Result
-------------------------------------------
x and y are the same type Strict Equality (===) Algorithm
Number String x == toNumber(y)
and toNumber does the following to a string argument:
toNumber:
Argument type Result
------------------------
String In effect evaluates Number(string)
“abc” -> NaN
“123” -> 123
Number('') returns 0. So that leaves you with 0==0 which is evaluated using Strict Equality (===) Algorithm
The Strict Equals Operator (===)
Type values Result
----------------------------------------------------------
Number x same value as y true
(but not NaN)
You can find the complete list # javascriptweblog.wordpress.com - truth-equality-and-javascript.
parseInt("") is NaN because the standard says so even if +"" is 0 instead (also simply because the standard says so, implying for example that "" == 0).
Don't look for logic in this because there's no deep profound logic, just history.
You are in my opinion making a BIG mistake... the sooner you correct it the better will be for your programming life with Javascript. The mistake is that you are assuming that every choice made in programming languages and every technical detail about them is logical. This is simply not true.
Especially for Javascript.
Please remeber that Javascript was "designed" in a rush and, just because of fate, it became extremely popular overnight. This forced the community to standardize it before any serious thought to the details and therefore it was basically "frozen" in its current sad state before any serious testing on the field.
There are parts that are so bad they aren't even funny (e.g. with statement or the == equality operator that is so broken that serious js IDEs warn about any use of it: you get things like A==B, B==C and A!=C even using just normal values and without any "special" value like null, undefined, NaN or empty strings "" and not because of precision problems).
Nonsense special cases are everywhere in Javascript and trying to put them in a logical frame is, unfortunately, a wasted effort. Just learn its oddities by reading a lot and enjoy the fantastic runtime environment it provides (this is where Javascript really shines... browsers and their JIT are a truly impressive piece of technology: you can write a few lines and get real useful software running on a gajillion of different computing devices).
The official standard where all oddities are enumerated is quite hard to read because aims to be very accurate, and unfortunately the rules it has to specify are really complex.
Moreover as the language gains more features the rules will get even more and more complex: for example what is for ES5 just another weird "special" case (e.g. ToPrimitive operation behavior for Date objects) becomes a "normal" case in ES6 (where ToPrimitive can be customized).
Not sure if this "normalization" is something to be happy about... the real problem is the frozen starting point and there are no easy solutions now (if you don't want to throw away all existing javascript code, that is).
The normal path for a language is starting clean and nice and symmetric and small. Then when facing real world problems the language gains (is infected by) some ugly parts (because the world is ugly and asymmetrical).
Javascript is like that. Except that it didn't start nice and clean and moreover there was no time to polish it before throwing it in the game.

Strange addition of numbers, why? [duplicate]

Why is it when I print/display the result of
eval("11.05") + eval("-11")
it comes out as 0.05000000000000071 instead of the expected 0.05. Is there something I am missing?
This has nothing to do with eval. In fact, this is what happens if you type in a console 11.05 - 11:
This is a consequence of how programming languages store floating-point numbers; they include a small error. If you want to read more about this, check this out.
This has nothing to do with eval (which you should avoid).
You get the same problem with 11.05 - 11.
This is just the usual floating point problem
As others have indicated, this is a floating point problem and has nothing to do with eval. Now for eval: you can easy avoid it here, using:
Number("11.05") + Number("-11");
To avoid the faulty outcome you could use toPrecision:
(Number("11.05") + Number("-11")).toPrecision(12);
// or if you want 0.05 to be the outcome
(Number("11.05") + Number("-11")).toPrecision(1);
The function eval is absolutely innocent here. The culprit is floating-point operation. If you do not expect a large number of numbers after the decimal, you may limit. But you can not avoid it.

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