numberFuncs.formatNumber   F
last analyzed

Complexity

Conditions 16
Paths 144

Size

Total Lines 69
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 1
Metric Value
cc 16
eloc 39
c 1
b 1
f 1
nc 144
nop 3
dl 0
loc 69
rs 2.4

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like numberFuncs.formatNumber often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/** global: UB */
2
3
UB.intMaxValue = 2147483647;
4
UB.intMinValue = -2147483648;
5
UB.floatMaxValue = 3.40282e+038; /// 038 or 056? .. it was originally 038F
6
UB.floatMinValue = -3.40282e+038;
7
UB.doubleMaxValue =  9223372036854775807;
8
UB.doubleMinValue = -9223372036854775808;
9
10
UB.roman1s = ["", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix"];
11
UB.roman10s = ["", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc"];
12
UB.roman100s = ["", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm"];
13
UB.roman1000s = ["", "m", "mm", "mmm", "mmmm", "", "", "", "", ""];
14
UB.roman = [UB.roman1s, UB.roman10s, UB.roman100s, UB.roman1000s];
15
16
UB.letterLegal = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "BB", "CC", "DD", "EE", "FF", "GG", "HH", "II", "JJ", "KK", "LL", "MM", "NN", "OO", "PP", "QQ", "RR", "SS", "TT", "UU", "VV", "WW", "XX", "YY", "ZZ", "AAA", "BBB", "CCC", "DDD", "EEE", "FFF", "GGG", "HHH", "III", "JJJ", "KKK", "LLL", "MMM", "NNN", "OOO", "PPP", "QQQ", "RRR", "SSS", "TTT", "UUU", "VVV", "WWW", "XXX", "YYY", "ZZZ", "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLL", "MMMM", "NNNN", "OOOO", "PPPP", "QQQQ", "RRRR", "SSSS", "TTTT", "UUUU", "VVVV", "WWWW", "XXXX", "YYYY", "ZZZZ", "AAAAA", "BBBBB", "CCCCC", "DDDDD", "EEEEE", "FFFFF", "GGGGG", "HHHHH", "IIIII", "JJJJJ", "KKKKK", "LLLLL", "MMMMM", "NNNNN", "OOOOO", "PPPPP", "QQQQQ", "RRRRR", "SSSSS", "TTTTT", "UUUUU", "VVVVV", "WWWWW", "XXXXX", "YYYYY", "ZZZZZ"];
17
UB.letterExcel = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH", "AI", "AJ", "AK", "AL", "AM", "AN", "AO", "AP", "AQ", "AR", "AS", "AT", "AU", "AV", "AW", "AX", "AY", "AZ", "BA", "BB", "BC", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BK", "BL", "BM", "BN", "BO", "BP", "BQ", "BR", "BS", "BT", "BU", "BV", "BW", "BX", "BY", "BZ", "CA", "CB", "CC", "CD", "CE", "CF", "CG", "CH", "CI", "CJ", "CK", "CL", "CM", "CN", "CO", "CP", "CQ", "CR", "CS", "CT", "CU", "CV", "CW", "CX", "CY", "CZ", "DA", "DB", "DC", "DD", "DE", "DF", "DG", "DH", "DI", "DJ", "DK", "DL", "DM", "DN", "DO", "DP", "DQ", "DR", "DS", "DT", "DU", "DV", "DW", "DX", "DY", "DZ"];
18
19
UB.decZeros = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
20
UB.hexChars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"];
21
UB.toDegrees = (180 / Math.PI);
22
UB.toRadians = (Math.PI / 180);
23
24
UB.minOf3 = function(num1, num2, num3){
25
	if (num1 < num2) {
26
		if (num1 < num3) {
27
			return num1;
28
		}
29
		return num3;
30
	}
31
	if (num2 < num3) {
32
		return num2;
33
	}
34
	return num3;
35
};
36
UB.maxOf3 = function(num1, num2, num3){
37
	if (num1 > num2) {
38
		if (num1 > num3) {
39
			return num1;
40
		}
41
		return num3;
42
	}
43
	if (num2 > num3) {
44
		return num2;
45
	}
46
	return num3;
47
};
48
49
UB.minOf4 = function(num1, num2, num3, num4){
50
	if (num1 < num2) {
51
		
52
		// 1, 3, 4
53
		if (num1 < num3) {
54
			
55
			// 1, 4
56
			if (num1 < num4) {
57
				return num1;
58
			}
59
			return num4;
60
		}
61
		
62
		// 3, 4
63
		if (num3 < num4) {
64
			return num3;
65
		}
66
		return num4;
67
		
68
	}
69
	
70
	// 2, 3, 4
71
	if (num2 < num3) {
72
		
73
		// 2, 4
74
		if (num2 < num4) {
75
			return num2;
76
		}
77
		return num4;
78
	}
79
	
80
	// 3, 4
81
	if (num3 < num4) {
82
		return num3;
83
	}
84
	return num4;
85
};
86
UB.maxOf4 = function(num1, num2, num3, num4){
87
	if (num1 > num2) {
88
		
89
		// 1, 3, 4
90
		if (num1 > num3) {
91
			
92
			// 1, 4
93
			if (num1 > num4) {
94
				return num1;
95
			}
96
			return num4;
97
		}
98
		
99
		// 3, 4
100
		if (num3 > num4) {
101
			return num3;
102
		}
103
		return num4;
104
		
105
	}
106
	
107
	// 2, 3, 4
108
	if (num2 > num3) {
109
		
110
		// 2, 4
111
		if (num2 > num4) {
112
			return num2;
113
		}
114
		return num4;
115
		
116
	}
117
	
118
	// 3, 4
119
	if (num3 > num4) {
120
		return num3;
121
	}
122
	return num4;
123
};
124
125
/** calc overlap of 2 numeric ranges */
126
UB.overlap = function(value1Start, value1End, value2Start, value2End){
127
	
128
	// swap if reversed
129
	if (value1Start > value1End) {
130
		var temp = value1Start;
131
		value1Start = value1End;
132
		value1End = temp;
133
	}
134
	if (value2Start > value2End) {
135
		temp = value2Start;
136
		value2Start = value2End;
137
		value2End = temp;
138
	}
139
	
140
	// exit if no overlap
141
	if (value1End < value2Start || value2End < value1Start) {
142
		return 0;
143
	}
144
	
145
	// return overlap of 2 ranges
146
	if (value1Start >= value2Start && value1End <= value2End) {
147
		return (value1End - value1Start);
148
	} else if (value2Start >= value1Start && value2End <= value1End) {
149
		return (value2End - value2Start);
150
	} else if (value1Start < value2Start && value1End <= value2End) {
151
		return (value1End - value2Start);
152
	} else if (value2Start < value1Start && value2End <= value1End) {
153
		return (value2End - value1Start);
154
	}
155
	return 0;
156
};
157
158
// distance between 2 lat/lon coords
159
UB.latLonDistance = function(latitude1, longitude1, latitude2, longitude2){
160
	
161
	// all lat/lons are floating point numbers in degrees
162
	
163
	var theta = longitude1 - longitude2;
164
	var miles = (Math.sin(latitude1*UB.toRadians)*Math.sin(latitude2*UB.toRadians)) + (Math.cos(latitude1*UB.toRadians)*Math.cos(latitude2*UB.toRadians)*Math.cos(theta*UB.toRadians));
165
	miles = Math.acos(miles);
166
	miles = (miles * UB.toDegrees);
167
	
168
	miles = miles * 60 * 1.1515;
169
	var feet = miles*5280;
170
	var yards = feet / 3;
171
	var kilometers = miles*1.609344;
172
	var meters = kilometers*1000;
173
	return [miles, feet, yards, kilometers, meters];
174
};
175
	
176
177
var stringFuncs = {
178
	
179
	/** CONVERT LEGAL LETTER TO NUMBER .. A = 1, B = 2, C = 3  */
180
	legalNumeralToNumber: function(zeroBased){
181
		var s = this.toString();
182
		return UB.letterLegal.indexOf(s.toUpperCase()) + (zeroBased ? 0 : 1);
183
	},
184
	/** CONVERT EXCEL COLUMN ID TO NUMBER .. A = 1, B = 2, C = 3  */
185
	excelColumnToNumber: function(zeroBased = false){
186
		var s = this.toString();
187
		return UB.letterExcel.indexOf(s.toUpperCase()) + (zeroBased ? 0 : 1);
188
	},
189
	
190
	hexToDecimal: function(onlyDigits = 0){
191
		var hex = this.toString();
192
		hex = hex.toUpperCase();
193
		
194
		// remove prefix
195
		if (hex.indexOf("0X") === 0){
196
			hex = hex.substr(2);
197
		}else if (hex.charAt(0) == "#"){
198
			hex = hex.substr(1);
199
		}
200
		
201
		if (onlyDigits) {
202
			hex = hex.substr(0, onlyDigits);
203
		}
204
		return int("0x" + hex);
205
	},
206
	
207
	binaryToDecimal: function(){
208
		var bin = this.toString();
209
		bin = bin.toUpperCase();
210
		
211
		// remove prefix
212
		if (bin.indexOf("0B") === 0){
213
			bin = bin.substr(2);
214
		}
215
		
216
		var byte = 0;
217
		for (var i = 0, il = bin.length, il2 = bin.length - 1;i<il;i++){
218
			byte += uint(bin.charAt(il2 - i)) * Math.pow(2,i);
219
		}
220
		return byte;
221
	},
222
	
223
	none:null
224
};
225
226
// register funcs
227
UB.registerFuncs(String.prototype, stringFuncs);
228
229
230
231
var numberFuncs = {
232
	
233 View Code Duplication
	distance: function(v2, type){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
234
		var v1 = this;
235
		// type .. 0=any, 1=pos, 2=neg
236
		var v = v2 - v1;
237
		if (type == 1) {
238
			return v > 0 ? v : -v;
239
		}else if (type == 2) {
240
			return v > 0 ? -v : v;
241
		}
242
		return v;
243
	},
244
	round: function(){
245
		return Math.round(this);
246
	},
247
	ceil: function(){
248
		return Math.ceil(this);
249
	},
250
	floor: function(){
251
		return Math.floor(this);
252
	},
253
	abs: function(negative = false){
254
		var v = this;
255
		if (negative){
256
			return v > 0 ? -v : v;
257
		}
258
		return v > 0 ? v : -v;
259
	},
260
	acos: function(degrees = false){
261
		var v = this;
262
		if (degrees) {
263
			return Math.acos(v) * UB.toDegrees;
264
		}
265
		return Math.acos(v);
266
	},
267
	asin: function(degrees = false){
268
		var v = this;
269
		if (degrees) {
270
			return Math.asin(v) * UB.toDegrees;
271
		}
272
		return Math.asin(v);
273
	},
274
	atan: function(degrees = false){
275
		var v = this;
276
		if (degrees) {
277
			return Math.atan(v) * UB.toDegrees;
278
		}
279
		return Math.atan(v);
280
	},
281
	atan2: function(x, degrees = false){
282
		var y = this;
283
		if (degrees) {
284
			return Math.atan2(y, x) * UB.toDegrees;
285
		}
286
		return Math.atan2(y, x);
287
	},
288
	exp: function(){
289
		var v = this;
290
		return Math.exp(v);
291
	},
292
	log: function(){
293
		var v = this;
294
		return Math.log(v);
295
	},
296
	pow: function(power){
297
		var base = this;
298
		return Math.pow(base, power)
299
	},
300
	sin: function(degrees = false){
301
		var angle = this;
302
		if (degrees) {
303
			return Math.sin(angle * UB.toRadians);
304
		}
305
		return Math.sin(angle);
306
	},
307
	cos: function(degrees = false){
308
		var angle = this;
309
		if (degrees) {
310
			return Math.cos(angle * UB.toRadians);
311
		}
312
		return Math.cos(angle);
313
	},
314
	tan: function(degrees = false){
315
		var angle = this;
316
		if (degrees) {
317
			return Math.tan(angle * UB.toRadians);
318
		}
319
		return Math.tan(angle);
320
	},
321
	sqrt: function(){
322
		var v = this;
323
		return Math.sqrt(v);
324
	},
325
	compare: function(v2){
326
		var v1 = this;
327
		if (v1 < v2) {
328
			return -1;
329
		}
330
		if (v1 > v2) {
331
			return 1;
332
		}
333
		return 0;
334
	},
335
	positive: function(){
336
		var val = this;
337
		return val > 0 ? val : -val;
338
	},
339
	negative: function(){
340
		var val = this;
341
		return val > 0 ? -val : val;
342
	},
343
	
344
	exists: function(zeroOK = false){
345
		var v = this;
346
		if (zeroOK) {
347
			return (v == v);
348
		}
349
		return v == v && v != 0;
350
	},
351
	
352
	
353
	min: function(num2){
354
		var num1 = this;
355
		if (num1 < num2) {
356
			return num1;
357
		}
358
		return num2;
359
	},
360
	max: function(num2){
361
		var num1 = this;
362
		if (num1 > num2) {
363
			return num1;
364
		}
365
		return num2;
366
	},
367
	atMost: function(limit){
368
		var num = this;
369
		return num > limit ? limit : num;
370
	},
371
	atLeast: function(limit){
372
		var num = this;
373
		return num < limit ? limit : num;
374
	},
375
	
376
	
377
378
	/** Render a percentage (25%) using 2 values */
379
	percentageToString: function(current, decimals = 0){
380
		var total = this;
381
		return ((current / total) * 100).roundTo(decimals) + "%";
382
	},
383
	
384
385
	// CONVERT TO ABBREVIATION .. 1.5K
386
	toAbbreviation: function(decimals = 1){
387
		var num = this;
388
		if (num < 0) {
389
			return "-" + (-num).toAbbreviation; // -5.2K, -5.2M ..
390
		}
391
		if (num < 1000) {
392
			return String(num); // 520
393
		}
394
		if (num < 1000000) {
395
			return (num / 1000).roundToDigits(decimals) + 'K'; // 5.2K
396
		}
397
		if (num < 1000000000) {
398
			return (num / 1000000).roundToDigits(decimals) + 'M'; // 5.2M
399
		}
400
		return (num / 1000000000).roundToDigits(decimals) + 'G'; // 5.2B
401
	},
402
	
403
	
404
	// CONVERT TO ROMAN
405
	toRomanNumeral: function(){
406
		var n = this;
407
		if (n < 1) {
408
			n = 1;
409
		}
410
		
411
		// exit quickly if single digit
412
		if (n <= 9) {
413
			return UB.roman1s[n];
414
		}
415
		
416
		// create roman number if longer
417
		var str = n.toString();
418
		var output = [];
419
		for (var n = 0, nl = str.length;n<nl;n++){
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable n already seems to be declared on line 406. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
420
			var series = ((nl - 1) - n);
421
			var charIndex = int(str.charAt(n));
422
			output.push(UB.roman[series][charIndex]);
423
		}
424
		return output.join("");
425
	},
426
	
427
	/** CONVERT TO LEGAL LETTER .. 1 = A, 2 = B, 3 = C .. AA, BB, CC */
428
	toLegalNumeral: function(){
429
		var n = this;
430
		if (n < 1) {
431
			n = 1;
432
		}
433
		return UB.letterLegal[n];
434
	},
435
	// CONVERT TO NORMAL LETTER .. A, B, C .. AB, AB, AC .. BA, BB, BC
436
	toLetterNumeral: function(){
437
		var n = this;
438
		if (n <= 26) {
439
			return UB.letterLegal[n];
440
		}
441
		return "?";
442
	},
443
	/** CONVERT TO EXCEL COLUMN ID .. 1 = A, 2 = B, 3 = C .. AA, AB, AC */
444
	toExcelColumn: function(zeroBased = false){
445
		var n = this;
446
		var min = zeroBased?0:1;
447
		if (n < min) {
448
			n = min;
449
		}
450
		return UB.letterExcel[zeroBased ? n : n-1];
451
	},
452
	
453
	// CONVERT TO ORDINAL FORMAT .. 1st, 2nd, 3rd
454
	toOrdinal: function(){
455
		var i = this;
456
		var j = i % 10;
457
		var k = i % 100;
458
		if (j == 1 && k != 11) {
459
			return i + "st";
460
		}
461
		if (j == 2 && k != 12) {
462
			return i + "nd";
463
		}
464
		if (j == 3 && k != 13) {
465
			return i + "rd";
466
		}
467
		return i + "th";
468
	},
469
	
470
	
471
	// OR
472
	or: function(returnVal, ifNull = 0){
473
		var n = this;
474
		if (n == ifNull) {
475
			return returnVal;
476
		}
477
		return n;
478
	},
479
	
480
	
481
	/** Calc padding for a given length */
482
	padding: function(multipleOf){
483
		var length = this;
484
		return (multipleOf - (length % multipleOf));
485
	},
486
	
487
	multipleOf: function(multipleOf){
488
		var value = this;
489
		return value + (multipleOf - (value % multipleOf));
490
	},
491
	
492
	/** Calc x % of the given value */
493
	percentage: function(percentWanted){
494
		var val100Percent = this;
495
		if (percentWanted == 100) {
496
			return val100Percent;
497
		}
498
		return val100Percent * (percentWanted / 100.0);
499
	},
500
	
501
	/** Calc the % of otherVal in relation to val100Percent */
502
	percentOf: function(otherVal){
503
		var val100Percent = this;
504
		return (otherVal / val100Percent) * 100.0;
505
	},
506
	
507
	/** Calc the difference between 2 numbers in %
508
	//  ... 100, 50 shows -50% difference
509
	//  ... 100, 150 shows 50% difference */
510
	percentDifference: function(otherVal){
511
		var val100Percent = this;
512
		return ((otherVal - val100Percent) / val100Percent) * 100.0;
513
	},
514
	
515
	/** Returns the number halfway between the 2 given numbers
516
		Value1 can be greater than Value2. */
517
	between: function(value2){
518
		return this.middle(value2);
519
	},
520
	
521
	/** Returns the number halfway between the 2 given numbers
522
		Value1 can be greater than Value2. */
523
	middle: function(value2){
524
		var value1 = this;
525
		if (value1 > value2) {
526
			return value2 + ((value1 - value2) / 2);
527
		}
528
		return value1 + ((value2 - value1) / 2);
529
	},
530
	
531
	calcScale: function(targetValue){
532
		var value = this;
533
		if (targetValue === 0 && value === 0) {
534
			return 0;
535
		}
536
		return (value / targetValue);
537
	},
538
	
539
	ensure: function(defaultVal){
540
		var value = this;
541
		if (value === 0) {
542
			return defaultVal;
543
		}
544
		return value;
545
	},
546
	
547
	snapToHigher: function(snapBy){
548
		var val = this;
549
		return Math.ceil(val / snapBy) * snapBy;
550
	},
551
	snapToLower: function(snapBy){
552
		var val = this;
553
		return Math.floor(val / snapBy) * snapBy;
554
	},
555
	snapTo: function(snapBy){
556
		var val = this;
557
		return Math.round(val / snapBy) * snapBy;
558
	},
559
	
560
	toInt: function(round){
561
		var num = this;
562
		if (!round || round == "truncate") {
563
			return parseInt(num);
564
		}
565
		if (round == "round") {
566
			return Math.round(num);
567
		}
568
		if (round == "floor") {
569
			return Math.floor(num);
570
		}
571
		if (round == "ceiling") {
572
			return Math.ceil(num);
573
		}
574
		return 0;
575
	},
576
	
577
	/**
578
	 * Formats a Number adding commas and the specified decimal digits.
579
	 * Supports the million/billion and lakh/crore system.
580
	 * 
581
	 * @param	system					"million" or "lakh"
582
	 * @param	decimals				-1 = keep exact decimals as number, 0 = no decimals, 1+ = specific decimals
583
	 * @param	alwaysShowDecimal		add decimal even if decimal part is 0
584
	 */
585
	formatNumber: function(system, decimals = -1, alwaysShowDecimal = false){
586
		var num = this;
587
		
588
		var commas = system == "lakh" ? 2 : 3;
589
590
		// test if number is negative
591
		var neg = false;
592
		if (num < 0) {
593
			neg = true;
594
			num = -num;
595
		}
596
		// get the left number
597
		var numStr = String(num);
598
		var hasDot = numStr.indexOf(".")>-1;
599
		if (hasDot) {
600
			var parts = numStr.split(".");
601
			var whole = parts[0];
602
			var decimal = parts[1];
603
		}else{
604
			whole = numStr;
605
			decimal = null;
606
		}
607
		
608
		// if at least 4 digits
609
		if (whole.length > 3) {
610
			
611
			// extract 3 digits first 
612
			var wholeRight3 = whole.substr(whole.length - 3, 3);
613
			whole = whole.substr(0, whole.length - 3);			
614
			
615
			// add million / crore seperators
616
			if (whole.length < commas) {
617
				whole = whole + "," + wholeRight3;
618
			}else {
619
				var thou = "";
620
				var rem = whole.substr(0, int(whole.length % commas));
621
				var l = ((int(whole.length / commas)*commas) - commas) + (whole.length % commas);
622
				for (var c = 0;l >= 0;l -= commas, c++){
0 ignored issues
show
Unused Code introduced by
The loop variable c is initialized by the loop but not used in the test. Consider using another type of loop if this is the intended behavior.
Loading history...
623
					thou = whole.substr(l, commas) + (c === 0 ? "" : ",") + thou;
624
				}
625
				whole = (rem == "" ? "" : rem + ",") + thou + "," + wholeRight3;
626
			}
627
		}
628
		
629
		// return with or without dot
630
		var result = whole;
631
		if (hasDot) {
632
			if (decimals > 0) {
633
				//  4.200
634
				result = whole + "." + decimal.substr(0, decimals).padRight("0", decimals);
635
			}else if (decimals === 0) {
0 ignored issues
show
Comprehensibility Documentation Best Practice introduced by
This code block is empty. Consider removing it or adding a comment to explain.
Loading history...
636
				//  4
637
				//result = whole;
638
			}else if (decimals === -1) {
639
				//  4.2
640
				result = whole + "." + decimal;
641
			}
642
			
643
		}else if (alwaysShowDecimal && decimals > 0) {
644
			
645
			//  4.0000
646
			result = whole + "." + decimals.repeat("0");
647
		}else {
0 ignored issues
show
Comprehensibility Documentation Best Practice introduced by
This code block is empty. Consider removing it or adding a comment to explain.
Loading history...
648
			
649
			//  4
650
			//result = whole;
651
		}
652
		return (neg ? "-" + result : result);
653
	},
654
	
655
	ensureNotNaN: function(instead = 0){
656
		var val = this;
657
		if (val != val) { /// fast isNaN check
658
			return instead;
659
		}
660
		return val;
661
	},
662
	
663
	scale: function(inputMin, inputMax, outputMin, outputMax, outputLimit = true, outputFlip = false){
664
		var input = this;
665
		
666
		// ensure input within limits
667
		if (input < inputMin) {
668
			input = inputMin;
669
		}
670
		if (input > inputMax) {
671
			input = inputMax;
672
		}
673
		
674
		// convert input to %
675
		var percent = ((1*(input - inputMin)) / (inputMax - inputMin));
676
		
677
		// convert % to output
678
		var output = (percent*(outputMax - outputMin)) + outputMin;
679
		
680
		// ensure output within limits
681
		if (outputLimit){
682
			if (output < outputMin) {
683
				output = outputMin;
684
			}
685
			if (output > outputMax) {
686
				output = outputMax;
687
			}
688
		}
689
		
690
		// flip output
691
		if (outputFlip) {
692
			output = ((outputMax - outputMin) - (output - outputMin)) + outputMin;
693
		}
694
		
695
		// return scaled, limit-checked output
696
		return output;
697
	},
698
	smartScale: function(inputMin, inputMax, outputMin, outputMax){
699
		var input = this;
700
		if (inputMin > inputMax) {
701
			if (outputMin > outputMax) {
702
				return input.flipWithin(inputMin, inputMax).scale(inputMax, inputMin, outputMax, outputMin, true, true);
703
			}
704
			return input.flipWithin(inputMin, inputMax).scale(inputMax, inputMin, outputMin, outputMax);
705
		}
706
		if (outputMin > outputMax) {
707
			return input.scale(inputMin, inputMax, outputMax, outputMin, true, true);
708
		}
709
		return input.scale(inputMin, inputMax, outputMin, outputMax);
710
	},
711
	
712
	flipWithin: function(min, max){
713
		var input = this;
714
		if (max < min) {
715
			return ((min - max) - (input - max)) + min;
716
		}
717
		return ((max - min) - (input - min)) + min;
718
	},
719
	
720
	limitToDigits: function(digits){
721
		var input = this;
722
		return parseFloat(input.toString().substr(0, digits));
723
	},
724
	limit: function(min, max){
725
		var input = this;
726
		
727
		// ensure ok
728
		if (input != input) { /// fast isNaN check
729
			return min;
730
		}
731
		
732
		// flip limits if in reverse order
733
		if (min > max) {
734
			var temp = max;
735
			max = min;
736
			min = temp;
737
		}
738
		
739
		// ensure within limits
740
		if (input < min) {
741
			return min;
742
		}else if (input > max) {
743
			return max;
744
		}
745
		return input;
746
	},
747
	limitToArray: function(array, extraMax = 0, extraMin = 0){
748
		var pointer = this;
749
		if (pointer <= -extraMin) {
750
			return -extraMin;
751
		}
752
		var last = (array.length + extraMax) - 1;
753
		if (last === -1) {
754
			return -extraMin;
755
		}else if (pointer > last) {
756
			return last;
757
		}
758
		return pointer;
759
	},
760
	
761
	wrap: function(min, max){
762
		var input = this;
763
		
764
		// flip limits if in reverse order
765
		if (min > max) {
766
			var temp = max;
767
			max = min;
768
			min = temp;
769
		}
770
		
771
		// ensure wrapped to limits
772
		var diff = (max - min) + 1;
773
		while (input < min) {
774
			input += diff;
775
		}
776
		while (input > max) {
777
			input -= diff;
778
		}
779
		return input;
780
	},
781
	wrapToMax: function(max){
782
		var value = this;
783
		var diff = max + 1;
784
		while (value < 0) {
785
			value += diff;
786
		}
787
		return value % diff;
788
	},
789
	
790
	/** Identical to modulo operator, except negative values are also supported, and brought into positive range.
791
		Value will never reach limit, just like the modulo operator.
792
		Simpler than `wrap` which takes `min` and `max`. */
793
	modulo: function(limit){
794
		var input = this;
795
		
796
		// ensure wrapped to limits
797
		while (input < 0) {
798
			input += limit;
799
		}
800
		while (input >= limit) {
801
			input -= limit;
802
		}
803
		return input;
804
	},
805
	
806
	roundToDigits: function(decimals = 4){
807
		var input = this;
808
		
809
		if (decimals <= 0) {
810
			return Math.round(input);
811
		}
812
		
813
		// Returns a number rounded to specified number of decimals
814
		var multiplier = Math.pow(10, decimals);
815
		return Math.round(input*multiplier)/multiplier;
816
	},
817
	roundTo: function(decimals){
818
		var input = this;
819
		
820
		// Returns a number rounded to specified number of decimals
821
		// Add zeros to always return those many decimals
822
		var num = input.roundToDigits(decimals).toString();
823
		if (decimals <= 0) {
824
			return num;
825
		}
826
		var add0 = 0;
827
		if (num.lastIndexOf(".") === -1){
828
			num = num+".";
829
			add0 = decimals;
830
		}else{
831
			add0 = decimals - ((num.length - num.lastIndexOf(".")) - 1);
832
		}
833
		while(add0 > 0){
834
			num = num+"0";
835
			add0 --;
836
		}
837
		return num;
838
	},
839
	
840
	
841
	
842
	// HEX
843
	toHex: function(digits = 6, withHash = true){
844
		var num = this;
845
		var zeros = ("0000000000000000000000000000000000").substr(0, digits - 1);
846
		return ((withHash ? "#" : "") + (zeros + num.toString(16).toUpperCase()).substr( -digits));
847
	},
848
	
849
	incrementWithin: function(min, max){
850
		var num = this;
851
		num++;
852
		if (num > max) {
853
			return min;
854
		}
855
		return num;
856
	},
857
	decrementWithin: function(min, max){
858
		var num = this;
859
		num--;
860
		if (num < min) {
861
			return max;
862
		}
863
		return num;
864
	},
865
	
866
	
867
	decimalToBinary: function(digits = 8, alt = false){
868
		if (alt){
869
			var byte = this;
870
			var bin = '';
871
			for (var i = 0;i<digits;i++){
872
				bin += String((byte & (0x80 >> i)) >> (7 - i));
873
			}
874
			return bin;
875
		}
876
		var num = this;
877
		var zeros = UB.decZeros.substr(0, digits - 1);
878
		return (zeros + num.toString(2)).substr( -digits);
879
	}, 
880
	
881
	
882
	
883
	// MISC MATH
884
	pad: function(length, addToEnd = false, padChar = '0'){
885
		var number = this;
886
		
887
		// num to text
888
		var result = String(number);
889
		
890
		// exit quickly if already reached target len
891
		if (result.length >= length) {
892
			return result;
893
		}
894
		
895
		
896
		// pad
897
		if (addToEnd) {
898
			while (result.length < length){
899
				result = result + padChar;
900
			}
901
		}else {
902
			while (result.length < length){
903
				result = padChar + result;
904
			}
905
		}
906
		
907
		
908
		return result;
909
	},
910
	interpolate: function(min, max){
911
		var progress = this;
912
		// progress = (0 to 1)
913
		return min + ((max - min) * progress);
914
	},
915
	hypot: function(b){
916
		var a = this;
917
		// sqrt(a^2 + b^2) without under/overflow.
918
		
919
		var r;
920
		var aAbs = (a > 0 ? a : -a);
921
		var bAbs = (b > 0 ? b : -b);
922
		if (aAbs > bAbs) {
923
			r = b/a;
924
			r = aAbs*Math.sqrt(1+r*r);
925
		} else if (b != 0) {
926
			r = a/b;
927
			r = bAbs*Math.sqrt(1+r*r);
928
		} else {
929
			r = 0.0;
930
		}
931
		return r;
932
	},
933
	apow: function(value){
934
		var pow = this;
935
		// input:	1,2,4,8,16,32,64
936
		// output:	1,2,3,4,5,6,7
937
		if (value == 1 || value === -1) return value;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
938
		var count = 0;
939
		while (value != 0) {
940
			//remainder = value % pow;
941
			value = value / pow;
942
			count++;
943
		}
944
		return count;
945
	},
946
	invert: function(){
947
		var value = this;
948
		// input:	0.1		0.5		1 	2 		8
949
		// output:	10		2		1	0.5		0.2
950
		return 1 / value;
951
	},
952
	powAbs: function(exponent){
953
		var x = this;
954
		// This function always returns a positive value that conforms to the expected Exponent curve.
955
		// Math.pow: If x is negative, and exponent is not an integer, returns NaN.
956
		if( x >= 0 ) {
957
			return Math.pow( x, exponent );
958
		}
959
		return Math.pow(-x, 1/exponent);
960
	},
961
	
962
	// count digits in number
963
	getWhole: function(){
964
		var val = this;
965
		
966
		// -10.235 has 2 whole digits
967
		return int(val);
968
	},
969
	setWhole: function(newval){
970
		var val = this;
971
		return newval + GetFractional(val);
972
	},
973
	getFractional: function(){
974
		var val = this;
975
		
976
		// -10.235 has 3 fractional digits
977
		var s = (val < 0 ? -val : val).toString();
978
		var i = s.indexOf(".");
979
		return (i === -1) ? int(val) : int(s.substr(i + 1));
980
	},
981
	setFractional: function(fraction){
982
		var val = this;
983
		return Number((parseInt(val).toString()) + "." + fraction.toString());
984
	},
985
	
986
	
987
	
988
	// SLOT INDEX
989
	minIndex: function(index2){
990
		var index1 = this;
991
		if (index1 <= -1) {
992
			return index2;
993
		}
994
		if (index2 <= -1) {
995
			return index1;
996
		}
997
		if (index1 < index2) {
998
			return index1;
999
		}
1000
		return index2;
1001
	},
1002
	maxIndex: function(index2){
1003
		var index1 = this;
1004
		if (index1 <= -1) {
1005
			return index2;
1006
		}
1007
		if (index2 <= -1) {
1008
			return index1;
1009
		}
1010
		if (index1 > index2) {
1011
			return index1;
1012
		}
1013
		return index2;
1014
	},
1015
	
1016
	
1017
	
1018
	none:null
1019
};
1020
1021
// register funcs
1022
UB.registerFuncs(Number.prototype, numberFuncs);
1023
1024