how to have one decimal point for numbers using angularJS - javascript

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

Related

Why doesn't my function correctly replace when using some regex pattern

This is an extension of this SO question
I made a function to see if i can correctly format any number. The answers below work on tools like https://regex101.com and https://regexr.com/, but not within my function(tried in node and browser):
const
const format = (num, regex) => String(num).replace(regex, '$1')
Basically given any whole number, it should not exceed 15 significant digits. Given any decimal, it should not exceed 2 decimal points.
so...
Now
format(0.12345678901234567890, /^\d{1,13}(\.\d{1,2}|\d{0,2})$/)
returns 0.123456789012345678 instead of 0.123456789012345
but
format(0.123456789012345,/^-?(\d*\.?\d{0,2}).*/)
returns number formatted to 2 deimal points as expected.
Let me try to explain what's going on.
For the given input 0.12345678901234567890 and the regex /^\d{1,13}(\.\d{1,2}|\d{0,2})$/, let's go step by step and see what's happening.
^\d{1,13} Does indeed match the start of the string 0
(\. Now you've opened a new group, and it does match .
\d{1,2} It does find the digits 1 and 2
|\d{0,2} So this part is skipped
) So this is the end of your capture group.
$ This indicates the end of the string, but it won't match, because you've still got 345678901234567890 remaining.
Javascript returns the whole string because the match failed in the end.
Let's try removing $ at the end, to become /^\d{1,13}(\.\d{1,2}|\d{0,2})/
You'd get back ".12345678901234567890". This generates a couple of questions.
Why did the preceding 0 get removed?
Because it was not part of your matching group, enclosed with ().
Why did we not get only two decimal places, i.e. .12?
Remember that you're doing a replace. Which means that by default, the original string will be kept in place, only the parts that match will get replaced. Since 345678901234567890 was not part of the match, it was left intact. The only part that matched was 0.12.
Answer to title question: your function doesn't replace, because there's nothing to replace - the regex doesn't match anything in the string. csb's answer explains that in all details.
But that's perhaps not the answer you really need.
Now, it seems like you have an XY problem. You ask why your call to .replace() doesn't work, but .replace() is definitely not a function you should use. Role of .replace() is replacing parts of string, while you actually want to create a different string. Moreover, in the comments you suggest that your formatting is not only for presenting data to user, but you also intend to use it in some further computation. You also mention cryptocurriencies.
Let's cope with these problems one-by-one.
What to do instead of replace?
Well, just produce the string you need instead of replacing something in the string you don't like. There are some edge cases. Instead of writing all-in-one regex, just handle them one-by-one.
The following code is definitely not best possible, but it's main aim is to be simple and show exactly what is going on.
function format(n) {
const max_significant_digits = 15;
const max_precision = 2;
let digits_before_decimal_point;
if (n < 0) {
// Don't count minus sign.
digits_before_decimal_point = n.toFixed(0).length - 1;
} else {
digits_before_decimal_point = n.toFixed(0).length;
}
if (digits_before_decimal_point > max_significant_digits) {
throw new Error('No good representation for this number');
}
const available_significant_digits_for_precision =
Math.max(0, max_significant_digits - digits_before_decimal_point);
const effective_max_precision =
Math.min(max_precision, available_significant_digits_for_precision);
const with_trailing_zeroes = n.toFixed(effective_max_precision);
// I want to keep the string and change just matching part,
// so here .replace() is a proper method to use.
const withouth_trailing_zeroes = with_trailing_zeroes.replace(/\.?0*$/, '');
return withouth_trailing_zeroes;
}
So, you got the number formatted the way you want. What now?
What can you use this string for?
Well, you can display it to the user. And that's mostly it. The value was rounded to (1) represent it in a different base and (2) fit in limited precision, so it's pretty much useless for any computation. And, BTW, why would you convert it to String in the first place, if what you want is a number?
Was the value you are trying to print ever useful in the first place?
Well, that's the most serious question here. Because, you know, floating point numbers are tricky. And they are absolutely abysmal for representing money. So, most likely the number you are trying to format is already a wrong number.
What to use instead?
Fixed-point arithmetic is the most obvious answer. Works most of the time. However, it's pretty tricky in JS, where number may slip into floating-point representation almost any time. So, it's better to use decimal arithmetic library. Optionally, switch to a language that has built-in bignums and decimals, like Python.

Javascript: concatenation with "," doesn't work

<button onclick="rzut()" />
<div id="wynik" />
<script type="text/javascript">
function rzut() {
document.getElementById("wynik").innerHTML = "Wynik to",Math.floor(Math.random()*6)+1;
}
</script>
For an unknown reason my script show only "Wynik to" and it skips the next part (math.floor etc)
Okay, let's go over some basics.
The first thing I would like to bring up is the concept of an Overloaded Operator. An overloaded operator, in short, is an operator that has different behaviour for different operands. An example of an overloaded operator in Javascript is +. For example:
var x = 4 + 4;
// x = 8
As you can see, adding two numeric values has the effect of summing the fields. But what about..
var x = "4" + "4";
// x = "44";
Well, because the types are strings, it behaves differently, hence it has an overloaded behaviour.
The + symbol will summate numeric values, but concatenate string values.
Bringing this forward to your example, you want to end up with a string value like..
"Wynik to,3"
Where 3 can vary. So let's look at it like this..
"Wynik to,X"
where X is some variable. Well.. this means you've got to build the string on the fly.. So following your approach (and not using some of the nice ES6 features that have been introduced), you can use our friendly overloaded + to accomplish this..
"Wynik to," + X
Where X is some random number between 1 and 6 therefore..
"Wynik to " + (Math.floor(Math.random()*6)+1);
So you'll see here, we've got a numeric value on the right hand side and a string value on the left hand side.
What Javascript does in this situation is what's known as arithmetic promotion, where all operands are promoted to the precision of the highest operand.
In this case, the right hand side of the equation is promoted to a string. Then, as we've seen above, our overloaded operator knows what to do with two strings.

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.
...................

javascript really strange behaviour

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.

How to compare locale dependent float numbers?

I need to compare a float value entered in a web form against a range. The problem is that the client computers may have various locale settings, meaning that user may use either "." or "," to separate the integer part from decimal one.
Is there a simple way to do it? As it is for an intranet and that they are only allowed to use IE, a VBScript is fine, even if I would prefer to use JavaScript.
EDIT: Let me clarify it a bit:
I cannot rely on the system locale, because, for example, a lot of our french customers use a computer with an english locale, even if they still use the comma to fill data in the web forms.
So I need a way to perform a check accross multiple locale "string to double" conversion.
I know that the raise condition is "what about numbers with 3 decimal digits", but in our environment, this kind of answer never happen, and if it happens, it will be threated as an out of range error due to the multiplication by a thousand, so it's not a real issue for us.
In Javascript use parseFloat on the text value to get a number. Similarly in VBScript use CDbl on the text value. Both should conform to the current locale settings enforce for the user.
This code should work:
function toFloat(localFloatStr)
var x = localFloatStr.split(/,|\./),
x2 = x[x.length-1],
x3 = x.join('').replace(new RegExp(x2+'$'),'.'+x2);
return parseFloat(x3);
// x2 is for clarity, could be omitted:
//=>x.join('').replace(new RegExp(x[x.length-1]+'$'),'.'+x[x.length-1])
}
alert(toFloat('1,223,455.223')); //=> 1223455.223
alert(toFloat('1.223.455,223')); //=> 1223455.223
// your numbers ;~)
alert(toFloat('3.123,56')); //=> 3123.56
alert(toFloat('3,123.56')); //=> 3123.56
What we do is try parsing using the culture of the user and if that doesn't work, parse it using an invariant culture.
I wouldn't know how to do it in javascript or vbscript exactly though.
I used KooiInc's answer but change it a bit, because it didn't reckon with some cases.
function toFloat(strNum) {
var full = strNum.split(/[.,]/);
if (full.length == 1) return parseFloat(strNum);
var back = full[full.length - 1];
var result = full.join('').replace(new RegExp(back + '$'), '.' + back);
return parseFloat(result);
}
Forbid using any thousands separator.
Give the user an example: "Reals should look like this: 3123.56 or 3123,56". Then simply change , to . and parse it.
You can always tell user that he did something wrong with a message like this:
"I don't understand what you mean by "**,**,**".
Please format numbers like "3123.56."

Categories

Resources