generate n length unique random numbers using javascript - javascript

Following are the rules:
Generate random numbers of length N.
Not more than two consecutive digits in a number should be the same.
I written code, but even though 2 same consecutive digits in a number are allowed, it's not working. All unique random numbers are generated.
I keep one temporary variable, which stores the previous number generated, if it matches the present generate number, then discard and generate again.
while (rnum.length<=7)
{
gennum = randomNumericChar();
if(rnum.length==0) {
rnum = rnum.concat(gennum);
prevnum = gennum;
} else if(gennum!=prevnum) {
rnum = rnum.concat(gennum);
prevnum = gennum;
}
}
return rnum;
FOund solution:
Hi, i got the solution. ` var rnum = "" ;
var random;
while(rnum.length<=7)
{
random= generaterandom();
if(rnum.length<2)
{
rnum = rnum.concat(random);
}else
{
//check whether previous two numbers are same, if not then append generated random number
if(!(random==rnum.charAt(rnum.length-1) && random==rnum.charAt(rnum.length-2)))
{
rnum = rnum.concat(random);
}
}
}`

This might be your solution:
function randomNumericChar(lastNumber) {
var num = Math.floor((Math.random() * 10) + 1);
if (lastNumber !== null && num === lastNumber) {
return randomNumericChar(lastNumber);
} else {
return num;
}
}
function createNumber(n) {
var randomNumber = '';
var lastChar = null;
while (randomNumber.length < n) {
var num = randomNumericChar(lastChar);
if (((randomNumber.length + 1) % 2) === 1) {
lastChar = num;
}
randomNumber += num;
}
return randomNumber;
}
var randomNumber = createNumber(10);
Edit: forgot about the fact that there might be 1 consecutive number.

Related

Error in true false output in Array Problem

Here's the question:
A Narcissistic 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 narcisstic:
1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153
Your code must return true or false (not 'true' and 'false') depending upon whether the given number is a Narcissistic number in base 10.
My Code is:
function narcissistic(value) {
let vLen = value.length;
let sum = 0;
for (let i = 0; i < vLen; i++) {
sum += Math.pow(value[i], vLen);
}
if (sum == value) {
return true;
} else {
return false;
}
}
But I'm getting errors. What should I do?
Numbers don't have .length, convert to string first
vLen[i], you cant treat a number as array, again, convert to string to use that syntax.
The return can be simplefied to return (sum === value);
function narcissistic(value) {
let sVal = value.toString();
let vLen = sVal.length;
let sum = 0;
for (let i = 0; i < vLen; i++) {
sum += Math.pow(sVal[i], vLen);
}
return (sum === value);
}
console.log(narcissistic(153));
console.log(narcissistic(111));
Well... There are several things wrong with this code, but I think there is mostly a problem with the types of your input.
I'll show you how you can cast the types of your input to make sure you work with the types you need:
Also... You should try to avoid using the == operator and try to use === instead (same goes for != and !==), because the == and != don't try to match the types, resulting in sometimes unpredictable results
function narcissistic(value) {
valueStr = String(value);
let vLen = valueStr.length;
let sum = 0;
for (let i = 0; i < vLen; i++) {
sum += Number(valueStr[i]) ** vLen;
}
if (sum === value) {
return true;
} else {
return false;
}
}
if(narcissistic(153)) {
console.log("narcissistic(153) is true!") // expected value: true
}
All the first 9 digits from 1 to 9 is Narcissistic number as there length is 1 and there addition is always same.
So, first we are checking weather the number is greater than 9 or not.
if(num>9) =>false than it's a narcissistic number.
-if(num>9) =>true than we have to split number into digits for that I have used x = num.toString().split('');. Which is first converting number to String and than using split() function to split it.
Than , we are looping through each digit and digitsSum += Math.pow(Number(digit), x.length); adding the power of digit to const isNarcissistic = (num) => { let x = 0; let digitsSum.
at the end, we are comparing both num & digitsSum if there are matched than number is narcissistic else not.
const isNarcissistic = (num) => {
let x = 0;
let digitsSum = 0;
if (num > 9) {
x = num.toString().split('');
x.forEach(digit => {
digitsSum += Math.pow(Number(digit), x.length);
});
if (digitsSum == num) {
return true;
} else {
return false;
}
} else {
return true;
}
}
console.log(isNarcissistic(153));
console.log(isNarcissistic(1634));
console.log(isNarcissistic(1433));
console.log(isNarcissistic(342));

Verify is Armstrong number with Javascript

I need to do a code to verify whether or not the entered number is an Armstrong number, but my code does not work for every number.
Could anyone tell me what am I missing? Are there any other ways to do this?
Thank you!
let e, x, d = 0;
let b = prompt("Enter a number");
x=b;
while (x > 0) {
e = x % 10;
x = parseInt(x/10);
d = d + (e*e*e);
}
if (b==d)
alert("given number is an armstrong number");
else
alert("given number is not an armstrong number");
<!DOCTYPE HTML>
<html>
<head>
<title>Armstrong</title>
</head>
<body>
</body>
</html>
I think the way you compute the result is wrong. According to Wikipedia, an Armstrong number, also called narcissistic number, has the following property:
[An Armstrong number] is a number that is the sum of its own digits each raised to the power of the number of digits.
You can compute it like this:
var number = prompt("Enter a number");
var numberOfDigits = number.length;
var sum = 0;
for (i = 0; i < numberOfDigits; i++) {
sum += Math.pow(number.charAt(i), numberOfDigits);
}
if (sum == number) {
alert("The entered number is an Armstrong number.");
} else {
alert("The entered number is not an Armstrong number.");
}
You can try this method, very easy to understand.
const armstrongNumber = (num) => {
const toArray = num.toString().split('').map(Number);
const newNum = toArray.map(a => {return a**3}).reduce((a, b) => a + b);
if(newNum == num){
console.log('This is an armstrong number');
}else{
console.log('This is not an armstrong number');
}
}
armstrongNumber(370);
//This is an armstrong number
Here is the solution to check Armstrong number without using Math Object.
function armstrongNum(number) {
const numberArr = String(number).split('');
const power = numberArr.length;
let TotalSum = numberArr.reduce((acc, cur) => {
return acc + (function(cur,power){
let curNum = Number(cur);
let product = 1;
while(power > 0) {
product *= curNum;
power --;
}
return product;
}(cur,power))
}, 0)
if (TotalSum === number) {
return true
}
return false
}
armstrongNum(153);
Here is an example of functional code for Armstrong Numbers.
<script>
function execute() {
var num1 = document.getElementById("Number1").value;
var num2 = document.getElementById("Number2").value;
var num3 = document.getElementById("Number3").value;
var concatNum = num1 + num2 + num3;
var num1Sqrt = num1 * num1 * num1;
var num2Sqrt = num2 * num2 * num2;
var num3Sqrt = num3 * num3 * num3;
if (num1Sqrt + num2Sqrt + num3Sqrt == concatNum) {
Answer.value = "The three integers you entered are Armstrong numbers.";
}
if (num1Sqrt + num2Sqrt + num3Sqrt != concatNum) {
Answer.value = "The three integers you entered are not Armstrong numbers.";
}
}
</script>
You first set your variables to what is entered, you then concatenate the string with the three integers.
You then square the three integers and set each value to a variable. You then have a basic check for equality, if the three squared values add up to your concatenated string then you have an Armstrong number.
This is how i solved mine:
function armstrong(num) {
var digits = num.toString().split('')
var realDigits = num
var a = 0
for (let i = 0; i < digits.length; i++){
digits[i] = Math.pow(digits[i], digits.length)
a += digits[i]
}
if (a == realDigits) {
console.log("Number is armstrong")
} else if (a != realDigits) {
console.log("Number is not armstrong")
}
}
armstrong(371)
//feel free to pass any value here
You can copy/paste and run this code at https://www.typescriptlang.org/play/
I hope this helps someone.
This works as well..
function isArmstrong (n) {
const res = parseInt(n, 10) === String(n)
.split('')
.reduce((sum, n) => parseInt(sum, 10) + n ** 3, 0);
console.log(n, 'is', res, 'Armstrong number')
return res
}
isArmstrong(153)
Here is another way to solve it.
let c = 153
let sum = 0;
let d = c.toString().split('');
console.log(d)
for(let i = 0; i<d.length; i++) {
sum = sum + Math.pow(d[i], 3)
}
if(sum == c) {
console.log("armstrong")
}
else {
console.log("not a armstrong")
}
Correct way to find Armstrong
var e, x, d = 0, size;
var b = prompt("Enter a number");
b=parseInt(b);
x=b;
size = x.toString().length;
while (x > 0) {
e = x % 10;
d = d + Math.pow(e,size);
x = parseInt(x/10);
}
//This is I solved without function
let num = prompt();
let num1 = num;
let sum = 0;
while(num > 0){
rem = num % 10;
sum = sum + Math.pow(rem, num1.length);
num = parseInt (num /10);
}
if (sum == num1) console.log("Armstrong");
else console.log("not Armstrong");
number is an Armstrong number or not.
let inputvalue=371
let spiltValue=inputvalue.toString().split('')
let output=0
spiltValue.map((item)=>output+=item**spiltValue.length)
alert(`${inputvalue} ${inputvalue==output? "is armstrong number" : "is not armstrong number"}`);
In order to get a Narcissistic/Armstrong number, you need to take the
length of the number as n for taking the power for summing the
value.
Here's another solution that works with an input >= 3 digits
(With Math.pow() each character is added as a number to the power of the array size)
const isArmstrongNumber = (n) => {
//converting to an array of digits and getting the array length
const arr = [...`${n}`].map(Number);
let power = arr.length;
const newNum = arr
.map((a) => {
return Math.pow(parseInt(a), power);
})
.reduce((a, b) => a + b);
return newNum == n;
};
console.log("Is it Armstrong? " + isArmstrongNumber(370));
console.log("Is it Armstrong? " + isArmstrongNumber(123));
console.log("Is it Armstrong? " + isArmstrongNumber(1634));
You can try for This, May this help for you:
<!DOCTYPE HTML>
<html>
<head>
<title>Armstrong</title>
</head>
<body>
</body>
</html>
<script>
var z,e,x,d=0;
var b=prompt("Enter a number");
x=parseInt(b);
while(x>0) //Here is the mistake
{
e=x%10;
x=parseInt(x/10);
d=d+(e*e*e);
console.log("d: "+d+" e: "+e);
}
if(parseInt(b)==d){
alert("given no is amstrong number");
}
else {
alert("given no is not an amstrong number");
}
</script>

Sum of all digits of a number

Given Problem:
Write a function called "sumDigits".
Given a number, "sumDigits" returns the sum of all its digits.
var output = sumDigits(1148);
console.log(output); // --> 14
If the number is negative, the first digit should count as negative.
var output = sumDigits(-316);
console.log(output); // --> 4
My code:
function sumDigits(num) {
return num.toString().split("").reduce(function(a, b){
return parseInt(a) + parseInt(b);
});
}
My code solves the problem for positive integers. Any hints on how should I go about solving the problem for negative integers? Please and thanks.
Edit: And what if the given number is 0? Is it acceptable to add an if statement to return 0 in such cases?
Check to see if the first character is a -. If so, b is your first numeral and should be negative:
function sumDigits(num) {
return num.toString().split("").reduce(function(a, b){
if (a == '-') {
return -parseInt(b);
} else {
return parseInt(a) + parseInt(b);
}
});
}
You could use String#match instead of String#split for a new array.
function sumDigits(num) {
return num.toString().match(/-?\d/g).reduce(function(a, b) {
return +a + +b;
});
}
console.log(sumDigits(1148)); // 14
console.log(sumDigits(-316)); // 4
Somebody who is looking for a solution without reduce functions etc. can take this approach.
function sumDigits(num) {
var val = 0, remainder = 0;
var offset = false;
if (num <0) {
offset = true;
num = num * -1;
}
while (num) {
remainder = num % 10;
val += remainder;
num = (num - remainder) / 10;
}
if (offset) {
val -= 2 * remainder;//If the number was negative, subtract last
//left digit twice
}
return val;
}
var output = sumDigits(-348);
console.log(output);
output = sumDigits(348);
console.log(output);
output = sumDigits(1);
console.log(output);
//Maybe this help: // consider if num is negative:
function sumDigits(num){
let negativeNum = false;
if(num < 0){
num = Math.abs(num);
negativeNum = true;
}
let sum = 0;
let stringNum = num.toString()
for (let i = 0; i < stringNum.length; i++){
sum += Number(stringNum[i]);
}
if(negativeNum){
return sum - (Number(stringNum[0]) * 2);
// stringNum[0] has the "-" sign so deduct twice since we added once
} else {
return sum;
}
}

JavaScript: formatting input method gives wrong values

I'm programming a method in JavaScript/JQuery which converts the value an user enters in an inputbox. The meaning is to make this input regional aware.
The functionality contains removing zeros at the beginning, placing thousand seperators and a decimal separator.
In this use case is the , symbol a thousand separator and the . dot the decimal separator
For example following input gets converted in following output.
12300 => 12,300.00
100 => 100.00
1023.456 => 1,023.456
Now There is still a problem with numbers, less than 100.
For example following input is malformed:
1 => 1,.00
2.05 => .05
20 => 20,.00
25.65 => .65
When I don't enter a decimal value in the input box, I get an unneeded thousand separator. When I enter a decimal value, I lose my content before the decimal separator.
The code:
$("#queryInstructedAmountFrom").change(function(){
var amount = $("#queryInstructedAmountFrom").val();
amount = removeZeros(amount);
var nonFractions = amount.match(/.{1,3}/g);
if(nonFractions == null) {
nonFractions = [];
nonFractions.push(amount);
}
var splittedValues = amount.split(/[,.]/);
amount = "";
if(splittedValues.length == 1) {
amount += splittedValues[0];
nonFractions = amount.match(/.{1,3}/g);
var firstIndex = amount.length % 3;
if(firstIndex != 0) {
var firstNumbers = amount.substr(0, firstIndex);
amount = amount.substr(firstIndex);
nonFractions = amount.match(/.{1,3}/g);
if(nonFractions == null) {
nonFractions = [];
nonFractions.push(amount);
}
amount = "";
amount += firstNumbers;
amount += thousandSeparator;
} else {
amount = "";
}
for(var i=0 ; i < nonFractions.length ; i++) {
amount += nonFractions[i];
if(i < (nonFractions.length - 1) && nonFractions.length != 1){
amount += thousandSeparator;
}
}
amount += decimalSeparator;
amount += "00";
} else {
for(var i=0 ; i < splittedValues.length - 1 ; i++) {
amount += splittedValues[i];
}
nonFractions = amount.match(/.{1,3}/g);
var firstIndex = amount.length % 3;
if(firstIndex == 0) {
nonFractions = amount.match(/.{1,3}/g);
}
if(firstIndex >= 1 && nonFractions != null) {
var firstNumbers = amount.substr(0, firstIndex);
amount = amount.substr(firstIndex);
nonFractions = amount.match(/.{1,3}/g);
if(nonFractions != null) {
amount = "";
amount += firstNumbers;
amount += thousandSeparator;
} else {
nonFractions = [];
nonFractions.push(amount);
}
} else {
amount = "";
}
for(var i=0 ; i < nonFractions.length ; i++) {
amount += nonFractions[i];
if(i < (nonFractions.length - 1) && nonFractions.length != 1){
amount += thousandSeparator;
}
}
amount += decimalSeparator;
amount += splittedValues[splittedValues.length -1];
}
$("#queryInstructedAmountFrom").val(amount);
});
});
function removeZeros(amount) {
while (amount.charAt(0) === '0') {
amount = amount.substr(1);
}
if(amount.length == 0){
amount = "0";
}
return amount;
}
What is going wrong?
What is going wrong?
I'd say almost everything. You have very unclear, messy code, I hardly following your logic, but you have several critical logic mistakes in code, for example:
1
1 is converted to 1,.00 because:
var splittedValues = amount.split(/[,.]/);
creates array with single element ['1']
var firstIndex = amount.length % 3;
1%3 == 1, so you're going into if condition, where amount += thousandSeparator; appends thousand separator, but you should add separator only if you have something after that
2
2.05 is wrong, because it goes into this branch:
var firstNumbers = amount.substr(0, firstIndex); // stores '2' into firstNumbers
amount = amount.substr(firstIndex); // sets amount to empty string
later, nonFractions is null:
nonFractions = [];
nonFractions.push(amount);
but firstNumbers is not used at all, ie its value is lost
3
also, you have:
nonFractions = amount.match(/.{1,3}/g);
var firstIndex = amount.length % 3;
if (firstIndex == 0) {
nonFractions = amount.match(/.{1,3}/g);
}
what is the sense of nonFractions re-init?
probably there are more errors and edge cases where this code fails, I suggest you to use library (like in other answers) or if you want to have your own code, here is simple version you can use:
$(document).ready(function() {
$("#queryInstructedAmountFrom").change(function() {
var val = parseFloat(('0' + $("#queryInstructedAmountFrom").val()).replace(/,/g, '')); // convert original text value into float
val = ('' + (Math.round(val * 100.0) / 100.0)).split('.', 2);
if (val.length < 2) val[1] = '00'; // handle fractional part
else while (val[1].length < 2) val[1] += '0';
var t = 0;
while ((val[0].length - t) > 3) { // append thousand separators
val[0] = val[0].substr(0, val[0].length - t - 3) + ',' + val[0].substr(val[0].length - t - 3);
t += 4;
}
$("#queryInstructedAmountFrom").val(val[0] + '.' + val[1]);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type="text" id="queryInstructedAmountFrom">
Why don't you use jQuery-Mask-Plugin?
<input type="text" id="money" />
and just invoke the plugin:
$('#money').mask('000.000.000.000.000,00', {reverse: true});
Plunker: https://plnkr.co/edit/PY7ihpS3Amtzeya9c6KN?p=preview
Refer to the below code updated.
$(document).ready(function() {
$("#queryInstructedAmountFrom").change(function() {
var amount = $("#queryInstructedAmountFrom").val();
amount = removeZeros(amount);
// format amount using 'ThousandFormattedValue' function
amount = ThousandFormattedValue(amount);
$("#queryInstructedAmountFrom").val(amount);
});
});
function removeZeros(amount) {
while (amount.charAt(0) === '0') {
amount = amount.substr(1);
}
if (amount.length == 0) {
amount = "0";
}
return amount;
}
function ThousandFormattedValue(iValue) {
// declaring variables and initializing the values
var numberArray, integerPart, reversedInteger, IntegerConstruction = "",
lengthOfInteger, iStart = 0;
// splitting number at decimal point by converting the number to string
numberArray = iValue.toString().split(".");
// get the integer part
integerPart = numberArray[0];
// get the length of the number
lengthOfInteger = integerPart.length;
// if no decimal part is present then add 00 after decimal point
if (numberArray[1] === undefined) {
numberArray.push("00");
}
/* split the integer part of number to individual digits and reverse the number
["4" , "3" , "2" , "1"] - after split
["1" , "2" , "3" , "4"] - after reverse
"1234" - after join
*/
reversedInteger = integerPart.split("").reverse().join("");
// loop through the string to add commas in between
while (iStart + 3 < lengthOfInteger) {
// get substring of very 3 digits and add "," at the end
IntegerConstruction += (reversedInteger.substr(iStart, 3) + ",");
// increase counter for next 3 digits
iStart += 3;
}
// after adding the commas add the remaining digits
IntegerConstruction += reversedInteger.substr(iStart, 3);
/* now split the constructed string and reverse the array followed by joining to get the formatted number
["1" , "2" , "3" , "," ,"4"] - after split
["4" , "," , "3" , "2" , "1"] - after reverse
"4,321" - after join
*/
numberArray[0] = IntegerConstruction.split("").reverse().join("");
// return the string as Integer part concatinated with decimal part
return numberArray.join(".");
}

How do we customize the built in Angular "currency" filter?

I'm using Angular "currency" filter to show price in a shopping cart. The prices are fetched from a back end server. So sometimes the price may not be available to show to the user. In that case I just want to show the user that the price is not available in the same field as of currency field. I can not show plain text in a currency filter. The only solution I found is to keep another text field to show/hide when a price is not available.But this is some what unnecessary I think. Is there any way to extend or override the built in "currency" filter of Angular js ?. Kindly appreciate some help.
<div class="large-12 medium-12 small-12 columns pad-none nzs-pro-list-item-price">
{{item.ItmPrice|currency}}
</div>
Create your custom filter which will internally use currency when value is present, otherwise it will return text which you want to show instead.
Markup
{{amount | customFormat:"USD$": "N/A"}}
Filter
.filter('customFormat', function($filter) {
return function(value, format, text) {
if (angular.isDefined(value) && value != null)
return $filter('currency')(value, format);
else
return text;
}
});
Working Plunkr
I feel the best way is to rewrite currency filter, so that you have fill control over Pattern, Grouping Separator, Decimal Separator & symbol position
<span>
{{26666662.5226 | fmtCurrency :"##.###,###" : "." : "," : "$" : "first"}}
</span>
Resluts in: $26.666.662,523
Filter:
app.filter("fmtCurrency", ['CurrencyService', function sasCurrency(CurrencyService) {
return function (amount, pattern, groupingSeparator, decimalSeparator, currencySymbol, symbolPosition) {
var patternInfo = CurrencyService.parsePattern(pattern, groupingSeparator, decimalSeparator);
var formattedCurrency = CurrencyService.formatCurrency(amount, patternInfo, groupingSeparator, decimalSeparator);
if (symbolPosition === 'last')
return formattedCurrency + currencySymbol;
else
return currencySymbol + formattedCurrency;
};
}])
Service: formatNumber which is the same function used in angular currency filter is being used here inside service
app.service("CurrencyService", function () {
var PATTERN_SEP = ';',
DECIMAL_SEP = '.',
GROUP_SEP = ',',
ZERO = '0',
DIGIT = "#";
var MAX_DIGITS = 22;
var ZERO_CHAR = '0';
return {
parsePattern: function (pattern, groupingSeparator, decimalSeparator) {
return parsePattern(pattern, groupingSeparator, decimalSeparator);
},
formatCurrency: function (amount, patternInfo, groupingSeparator, decimalSeparator) {
return formatNumber(amount, patternInfo, groupingSeparator, decimalSeparator);
}
}
/*
* Currency formatter utility
*/
function isUndefined(value) { return typeof value === 'undefined'; }
/**
* main function for parser
* #param str {string} pattern to be parsed (e.g. #,##0.###).
*/
function parsePattern(pattern, groupSep, decimalSep) {
DECIMAL_SEP = decimalSep;
GROUP_SEP = groupSep;
var p = {
minInt: 1,
minFrac: 0,
maxFrac: 0,
posPre: '',
posSuf: '',
negPre: '',
negSuf: '',
gSize: 0,
lgSize: 0
};
var ZERO = '0',
DIGIT = "#";
var parts = pattern.split(PATTERN_SEP),
positive = parts[0],
negative = parts[1];
var parts = positive.split(DECIMAL_SEP),
integer = parts[0],
fraction = parts[1];
console.log(parts);
p.posPre = integer.substr(0, integer.indexOf(DIGIT));
if (fraction) {
for (var i = 0; i < fraction.length; i++) {
var ch = fraction.charAt(i);
console.log(ch, ZERO, DIGIT);
if (ch == ZERO)
p.minFrac = p.maxFrac = i + 1;
else if (ch == DIGIT)
p.maxFrac = i + 1;
else
p.posSuf += ch;
}
}
var groups = integer.split(GROUP_SEP);
p.gSize = groups[1] ? groups[1].length : 0;
p.lgSize = (groups[2] || groups[1]) ? (groups[2] || groups[1]).length : 0;
if (negative) {
var trunkLen = positive.length - p.posPre.length - p.posSuf.length,
pos = negative.indexOf(DIGIT);
p.negPre = negative.substr(0, pos).replace(/\'/g, '');
p.negSuf = negative.substr(pos + trunkLen).replace(/\'/g, '');
} else {
// hardcoded '-' sign is fine as all locale use '-' as MINUS_SIGN. (\u2212 is the same as '-')
p.negPre = '-' + p.posPre;
p.negSuf = p.posSuf;
}
return p;
}
function isString(value) { return typeof value === 'string'; }
function isNumber(value) { return typeof value === 'number'; }
/**
* Format a number into a string
* #param {number} number The number to format
* #param {{
* minFrac, // the minimum number of digits required in the fraction part of the number
* maxFrac, // the maximum number of digits required in the fraction part of the number
* gSize, // number of digits in each group of separated digits
* lgSize, // number of digits in the last group of digits before the decimal separator
* negPre, // the string to go in front of a negative number (e.g. `-` or `(`))
* posPre, // the string to go in front of a positive number
* negSuf, // the string to go after a negative number (e.g. `)`)
* posSuf // the string to go after a positive number
* }} pattern
* #param {string} groupSep The string to separate groups of number (e.g. `,`)
* #param {string} decimalSep The string to act as the decimal separator (e.g. `.`)
* #param {[type]} fractionSize The size of the fractional part of the number
* #return {string} The number formatted as a string
*/
function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
if (!(isString(number) || isNumber(number)) || isNaN(number)) return '';
var isInfinity = !isFinite(number);
var isZero = false;
var numStr = Math.abs(number) + '',
formattedText = '',
parsedNumber;
if (isInfinity) {
formattedText = '\u221e';
} else {
parsedNumber = parse(numStr, '.');
roundNumber(parsedNumber, fractionSize, pattern.minFrac, pattern.maxFrac);
var digits = parsedNumber.d;
var integerLen = parsedNumber.i;
var exponent = parsedNumber.e;
var decimals = [];
isZero = digits.reduce(function (isZero, d) { return isZero && !d; }, true);
// pad zeros for small numbers
while (integerLen < 0) {
digits.unshift(0);
integerLen++;
}
// extract decimals digits
if (integerLen > 0) {
decimals = digits.splice(integerLen, digits.length);
} else {
decimals = digits;
digits = [0];
}
// format the integer digits with grouping separators
var groups = [];
if (digits.length >= pattern.lgSize) {
groups.unshift(digits.splice(-pattern.lgSize, digits.length).join(''));
}
while (digits.length > pattern.gSize) {
groups.unshift(digits.splice(-pattern.gSize, digits.length).join(''));
}
if (digits.length) {
groups.unshift(digits.join(''));
}
formattedText = groups.join(groupSep);
// append the decimal digits
if (decimals.length) {
formattedText += decimalSep + decimals.join('');
}
if (exponent) {
formattedText += 'e+' + exponent;
}
}
if (number < 0 && !isZero) {
return pattern.negPre + formattedText + pattern.negSuf;
} else {
return pattern.posPre + formattedText + pattern.posSuf;
}
}
function parse(numStr, decimalSep) {
var exponent = 0, digits, numberOfIntegerDigits;
var i, j, zeros;
DECIMAL_SEP = decimalSep;
// Decimal point?
if ((numberOfIntegerDigits = numStr.indexOf(DECIMAL_SEP)) > -1) {
numStr = numStr.replace(DECIMAL_SEP, '');
}
// Exponential form?
if ((i = numStr.search(/e/i)) > 0) {
// Work out the exponent.
if (numberOfIntegerDigits < 0) numberOfIntegerDigits = i;
numberOfIntegerDigits += +numStr.slice(i + 1);
numStr = numStr.substring(0, i);
} else if (numberOfIntegerDigits < 0) {
// There was no decimal point or exponent so it is an integer.
numberOfIntegerDigits = numStr.length;
}
// Count the number of leading zeros.
for (i = 0; numStr.charAt(i) === ZERO_CHAR; i++) {/* jshint noempty: false */ }
if (i === (zeros = numStr.length)) {
// The digits are all zero.
digits = [0];
numberOfIntegerDigits = 1;
} else {
// Count the number of trailing zeros
zeros--;
while (numStr.charAt(zeros) === ZERO_CHAR) zeros--;
// Trailing zeros are insignificant so ignore them
numberOfIntegerDigits -= i;
digits = [];
// Convert string to array of digits without leading/trailing zeros.
for (j = 0; i <= zeros; i++ , j++) {
digits[j] = +numStr.charAt(i);
}
}
// If the number overflows the maximum allowed digits then use an exponent.
if (numberOfIntegerDigits > MAX_DIGITS) {
digits = digits.splice(0, MAX_DIGITS - 1);
exponent = numberOfIntegerDigits - 1;
numberOfIntegerDigits = 1;
}
return { d: digits, e: exponent, i: numberOfIntegerDigits };
}
/**
* Round the parsed number to the specified number of decimal places
* This function changed the parsedNumber in-place
*/
function roundNumber(parsedNumber, fractionSize, minFrac, maxFrac) {
var digits = parsedNumber.d;
var fractionLen = digits.length - parsedNumber.i;
// determine fractionSize if it is not specified; `+fractionSize` converts it to a number
fractionSize = (isUndefined(fractionSize)) ? Math.min(Math.max(minFrac, fractionLen), maxFrac) : +fractionSize;
// The index of the digit to where rounding is to occur
var roundAt = fractionSize + parsedNumber.i;
var digit = digits[roundAt];
if (roundAt > 0) {
// Drop fractional digits beyond `roundAt`
digits.splice(Math.max(parsedNumber.i, roundAt));
// Set non-fractional digits beyond `roundAt` to 0
for (var j = roundAt; j < digits.length; j++) {
digits[j] = 0;
}
} else {
// We rounded to zero so reset the parsedNumber
fractionLen = Math.max(0, fractionLen);
parsedNumber.i = 1;
digits.length = Math.max(1, roundAt = fractionSize + 1);
digits[0] = 0;
for (var i = 1; i < roundAt; i++) digits[i] = 0;
}
if (digit >= 5) {
if (roundAt - 1 < 0) {
for (var k = 0; k > roundAt; k--) {
digits.unshift(0);
parsedNumber.i++;
}
digits.unshift(1);
parsedNumber.i++;
} else {
digits[roundAt - 1]++;
}
}
// Pad out with zeros to get the required fraction length
for (; fractionLen < Math.max(0, fractionSize); fractionLen++) digits.push(0);
// Do any carrying, e.g. a digit was rounded up to 10
var carry = digits.reduceRight(function (carry, d, i, digits) {
d = d + carry;
digits[i] = d % 10;
return Math.floor(d / 10);
}, 0);
if (carry) {
digits.unshift(carry);
parsedNumber.i++;
}
}
})
$provide.decorator('currencyFilter', ['$delegate',
function ($delegate) {
var crncyFilter = $delegate;
var extendsFilter = function () {
var res = crncyFilter.apply(this, arguments);
if (arguments[2]) {
var digi1 = arguments[2] || 2;
return arguments[1] + Number(arguments[0]).toFixed(digi1);
}
else {
if (arguments[1] == "¥") {
return arguments[1] + Number(arguments[0]).toFixed(1);
}
}
};
return extendsFilter;
}]);
This is the way to Override Decimal digit

Categories