Generate string from integer with arbitrary base in JavaScript - javascript

In JavaScript you can generate a string from a number like this:
(123).toString(36) // => "3f"
If you try to do arbitrary base:
(123).toString(40)
You get
Uncaught RangeError: toString() radix argument must be between 2 and 36
at Number.toString (<anonymous>)
at <anonymous>:1:7
Wondering how to do this to generate a string given an arbitrary alphabet. So say you have this alphabet:
abcdefghijklmnopqrstuvwxyz0123456789+-
Then it would be like:
toString(123, 'abcdefghijklmnopqrstuvwxyz0123456789+-')
And it would print something out (I have no idea what) such as 3+, picking from the alphabet.
Wondering how to do this in JavaScript, not sure if the "radix" has anything to do with it. Thank you.
Update: Looking how to reverse it as well, aka fromString(string).

While you asked for a parseInt for an arbitrary length, you could use the given string and reduce it by multiplying the former reduce value with the code length and adding the numerical value of the position of the code character.
Additional is the toString function supplied.
function parseInt(value, code) {
return [...value].reduce((r, a) => r * code.length + code.indexOf(a), 0);
}
function toString(value, code) {
var digit,
radix= code.length,
result = '';
do {
digit = value % radix;
result = code[digit] + result;
value = Math.floor(value / radix);
} while (value)
return result;
}
console.log(parseInt('dj', 'abcdefghijklmnopqrstuvwxyz0123456789+-'));
console.log(toString(123, 'abcdefghijklmnopqrstuvwxyz0123456789+-'));
console.log(parseInt('a', 'abcdefghijklmnopqrstuvwxyz0123456789+-'));
console.log(toString(0, 'abcdefghijklmnopqrstuvwxyz0123456789+-'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

You can simulate that doing:
const toString = (number, alphabet) => {
let result = "";
while (number) {
const digit = number%alphabet.length;
number = (number/alphabet.length)|0;
result = alphabet[digit] + result;
}
return result || alphabet[0];
}
//////////////////// For the opposite, you can use this:
const fromStringBuilder = (alphabet) => {
const alphabetKeys = {};
for (let i = 0; i < alphabet.length; i++) {
alphabetKeys[alphabet[i]] = i;
}
return (string) => {
return [...string].reduce((a,v) => a * alphabet.length + alphabetKeys[v],0);
}
}
//////////////////// Here you have example usage:
toAlphabet = (number) => toString(number, 'abcdefghijklmnopqrstuvwxyz0123456789+-')
fromAlphabet = fromStringBuilder('abcdefghijklmnopqrstuvwxyz0123456789+-')
console.log(fromAlphabet("3+")) // 1138
console.log(toAlphabet(1138)) // "3+"
console.log(toAlphabet(fromAlphabet("3+"))) // "3+"
Note: alphabet must be a string with at least two chars. Otherwise, the loop will be infinite.
Note 2: you have to pass the alphabet in the reverse order from your example to achieve the same exact output.

This works for any base higher than 2. All you have to do is populate the keys array, while the base is calculated by the number of keys.
The output of toString(123, 'abcdefghijklmnopqrstuvwxyz0123456789+-') would be dj.
The output of fromString('dj', 'abcdefghijklmnopqrstuvwxyz0123456789+-') would be 123.
Run the snippet at the bottom of the code to see.
This is the code:
// Converts a string back to it's original number form
function fromString(string, keys)
{
var base = keys.length;
var value = 0;
if(base >= 2)
for(var i=0; i<string.length; i++)
{
if(keys.indexOf(string[i]) != -1) value += keys.indexOf(string[i])*Math.pow(base,string.length - i - 1);
else return 'Invalid code.';
}
return value;
}
// Converts a number from decimal base to base of keys.length
// also, it assumes you enter correct data
function toString(number, keys)
{
var ready = false;
var base = keys.length;
var result = [];
if(base >= 2)
while(true)
{
result.unshift(keys[number % base]);
number = Math.floor(number/base);
if(number < 1) break;
}
return result.join('');
}
// Function that handles events on button click
function encryptDecrypt()
{
var keys = document.getElementById('getTheKeys').value.split('');
var encrypt = document.getElementById('encrypt').value;
var encrypted = document.getElementById('encrypted');
var decrypt = document.getElementById('decrypt').value;
var decrypted = document.getElementById('decrypted');
if(keys != '' && keys.length > 1)
{
if(encrypt != '' && parseInt(encrypt)) encrypted.value = toString(parseInt(encrypt), keys);
if(decrypt != '') decrypted.value = fromString(decrypt, keys);
}
}
.giveMeSomeSpace
{
padding-left:47px;
}
<table>
<tr>
<td colspan="2"><label for="getTheKeys">Enter the key string: </label><input type="text" id="getTheKeys" value="abcdefghijklmnopqrstuvwxyz0123456789+-" size="53"/></td>
<tr>
<tr>
<td><label for="encrypt">Encrypt: </label><input type="text" id="encrypt" value="" placeholder="Enter a number"/></td>
<td class="giveMeSomeSpace"><label for="encrypted">Encrypted: </label><input type="text" id="encrypted" value="" readonly="readonly" /></td>
<tr>
<tr>
<td><label for="decrypt">Decrypt: </label><input type="text" id="decrypt" value="" placeholder="Enter a key combination"/></td>
<td class="giveMeSomeSpace"><label for="decrypted">Decrypted: </label><input type="text" id="decrypted" value="" readonly="readonly" /></td>
<tr>
</table>
<input type="button" id="checkNow" value="Go" onclick="encryptDecrypt();" />

Let's make a simple function for base 10 to base N.
function b102bN (n,b, r = []){
var getNumeral = d => d < 10 ? d : String.fromCharCode(d+87);
return n ? (r.unshift(getNumeral(n%b)), b102bN(~~(n/b), b, r)) : r.join("");
}
console.log(b102bN(123,36));
console.log(b102bN(1453,40)); // obviously base 40 requires interesting characters as numerals

Related

if Input: 8-e Expected Output: 2|4|6|8

Question 2: The input consist of a string, "o" represents odd number, "e" represents even number to be printed
Example 1.
Input: 8-e
Expected Output: 2|4|6|8
Example 2.
Input: 6-o
Expected Output: 1|3|5
Example 3.
Input: 1-o
Expected Output: 1
if have tried with for loop, but I'am a beginner so I'am confused with(-e)
const evenOdd = (number) => {
let evenvalue = [];
let oddValue=[];
for(let i =0; i<=number; i++){
if(number%i==0)
evenvalue.push(i);
console.log(evenvalue);
}if(number%i!=0){
oddValue.push(i);
console.log(oddValue);
}
};
evenOdd(9);
You could take a while statement and get a start value of one plus an offset of one if the wanted type is even. Then iterate and add the value to the result set until the value is greater than the maximum value.
function fn(request) {
var [max, type] = request.split('-'),
i = 1 + (type === 'e'),
result = [];
while (i <= max) {
result.push(i);
i += 2;
}
return result;
}
console.log(...fn('8-e'));
console.log(...fn('6-o'));
console.log(...fn('1-o'));
You will need to extract the letter and the number from you string first. One easy way to do that :
const evenOdd = (s) => {
let odd = s.length-1 ==='o';
let number = Number(s.substring(0, s.length-2));
let evenvalue = [];
...
if(odd){...} else {...}
};
You could also use split() or if the pattern was more complicated, a Regex.
You can split on - and add based on type add values upto the number
Split the given input by -, first value represents max number and second represents it's type
Check the type if it is even add the even values start from 2 and upto to the max number else start from 1, and join them with | in the end
let func = (input) => {
let [num, type] = input.split('-')
let arr = []
let i = 1 + (type === 'e')
while (i <= num) {
arr.push(i)
i += 2
}
return arr.join('|')
}
console.log(func('8-e'))
console.log(func('1-o'))
console.log(func('6-o'))
Basically, don't supply a number to the function, supply a string and then parse the string. That is, don't try and give the function 9-e, give it '9-e'.
Get the parts of the input by splitting on -.
Turn the number into a number.
Give 0 for even, 1 for odd (x % 2 is 0 for even number, 1 for odd).
Build the results.
function listNumbers(constraint)
{
const parts = constraint.split('-');
const number = Number(parts[0]);
const numberType = parts[1] === 'e' ? 0:1;
let result = [];
for(let i = 1; i <= number; i++)
{
if(i%2 === numberType)
{
result.push(i);
}
}
return result;
}
console.log(listNumbers('8-e'));
Or if you want make the code look clever:
function listNumbers(constraint)
{
const parts = constraint.split('-');
const number = Number(parts[0]);
const numberType = parts[1] === 'e' ? 0:1;
return Array.from(Array(number), (x,i) => i + 1 ).filter(x => x%2 == numberType);
}
console.log(listNumbers('8-e'));

How to get sum of highest 5 values of an array using Javascript or Jquery?

I have an array of 6 values where 6th value is optional (i.e. if user does not input 6th value, the first 5 values will be calculated). I want to sum highest 5 values of them.
My Javascript Code:
function calculate_merit_point(){
var s1 = eval(document.getElementById('sub_no1').value);
var s2 = eval(document.getElementById('sub_no2').value);
var s3 = eval(document.getElementById('sub_no3').value);
var s4 = eval(document.getElementById('sub_no4').value);
var s5 = eval(document.getElementById('sub_no5').value);
var s6 = eval(document.getElementById('sub_no6').value);
var vals = [s1,s2,s3,s4,s5,s6];
function arraySum(arr) {
if (!arr) {
return false;
} else {
var sum = 0;
for (var i = 0, len = arr.length; i < len; i++) {
sum += arr[i];
}
return sum;
}
}
sum = arraySum(vals.sort(function(a, b) {
return b - a;
}).slice(0, 5));
if(isNaN(tt)){
$('#agr').text('0');
} else {
$('#agr').text(sum);
}
}
Now suppose
s1 = 30
s2 = 31
s3 = 32
s4 = 33
s5 = 34
s6 = 35
It should be 31+32+33+34+35 = 165. but it is displaying the value 162.
As per my requirement (6th value optional), if I do not give any value to s6, it is displaying the value 228.
I have tried This, but if I do not give the 6th (optional) value, it is showing the value 0. If I give the value 35 in s6, it is showing sum value 233.
What should I do ?
UPDATE & RESOLVED
My code was correct. But something was creating problem with the code eval(). I replaced it with Number() and it was resolved.
Thank you all.
This would be a great opportunity to use .reduce. Which will return a single value given an array. While we're "looping" through the array, we will determine the lowest value, and then subtract that from the result. Also, you're clearly using jQuery to apply the .text() so, may as well use it to get the .val() of each of your inputs. Then we'll use parseInt with a check to return 0 in the event of an error/invalid result
JSFIDDLE
HTML
<input id="sub_no1" value="30" />
<input id="sub_no2" value="31" />
<input id="sub_no3" value="32" />
<input id="sub_no4" value="33" />
<input id="sub_no5" value="34" />
<input id="sub_no6" value="35" />
<p id="agr"></p>
JS
$(function() {
function calculate_merit_point() {
var s1 = getValue($('#sub_no1'));
var s2 = getValue($('#sub_no2'));
var s3 = getValue($('#sub_no3'));
var s4 = getValue($('#sub_no4'));
var s5 = getValue($('#sub_no5'));
var s6 = getValue($('#sub_no6'));
var vals = [s1, s2, s3, s4, s5, s6];
function getValue(el) {
return parseInt(el.val(), 10) || 0;
}
function arraySum(arr) {
if (!arr) {
return 0;
} else {
var lowest = Infinity;
return vals.reduce(function(sum, val) {
if (val < lowest){ lowest = val; }
return sum + val;
}, 0) - lowest;
}
}
$('#agr').text(arraySum(vals));
}
calculate_merit_point();
})
You can sum more easily with reduce, and subtract the highest value with Math.max using this ES6 code:
var vals = [30,31,32,33,34,35,36];
// Get sum
var sum = vals.reduce( (a,b) => a+b, 0 );
// Subtract highest value
if (vals.length == 6) sum -= Math.max(...vals);
// Output result
console.log(sum);
Here is that code integrated with the element names you mention in your code, but using jQuery also for the first part:
function calculate_merit_point(){
// Get all six input elements by using jQuery with a smarter selector:
var vals = $('[id^=sub_no]').map(function () {
return parseInt($(this).val()); // get the value as numeric for each of them
}).get().filter(n => !isNaN(n)); // filter the result to get real numbers only
// get sum
var sum = vals.reduce( (a,b) => a+b, 0 );
// Remove greatest value from it if we have 6 numbers
if (vals.length == 6) sum -= Math.max(...vals);
// Output the result.
$('#agr').text(sum);
}
calculate_merit_point();
$('input').on('input', calculate_merit_point);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="sub_no1" value="1"><br>
<input id="sub_no2" value="2"><br>
<input id="sub_no3" value="3"><br>
<input id="sub_no4" value="4"><br>
<input id="sub_no5" value="5"><br>
<input id="sub_no6" value="6"><br>
<hr>
Sum: <span id="agr"></span>
You can adjust the values when running the above snippet and the sum will adapt.
ES5 equivalent
For when you don't have ES6 support:
function calculate_merit_point(){
// Get all six input elements by using jQuery with a smarter selector:
var vals = $('[id^=sub_no]').map(function () {
return parseInt($(this).val()); // get the value as numeric for each of them
}).get().filter(function (n) {
return !isNaN(n); // filter the result to get real numbers only
});
// get sum
var sum = vals.reduce(function (a,b) {
return a+b;
}, 0);
// Remove greatest value from it if we have 6 numbers
if (vals.length == 6) sum -= Math.max.apply(Math, vals);
// Output the result.
$('#agr').text(sum);
}
calculate_merit_point();
$('input').on('input', calculate_merit_point);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="sub_no1" value="1"><br>
<input id="sub_no2" value="2"><br>
<input id="sub_no3" value="3"><br>
<input id="sub_no4" value="4"><br>
<input id="sub_no5" value="5"><br>
<input id="sub_no6" value="6"><br>
<hr>
Sum: <span id="agr"></span>

which are alternative of tofixed() in javascript [duplicate]

Suppose I have a value of 15.7784514, I want to display it 15.77 with no rounding.
var num = parseFloat(15.7784514);
document.write(num.toFixed(1)+"<br />");
document.write(num.toFixed(2)+"<br />");
document.write(num.toFixed(3)+"<br />");
document.write(num.toFixed(10));
Results in -
15.8
15.78
15.778
15.7784514000
How do I display 15.77?
Convert the number into a string, match the number up to the second decimal place:
function calc(theform) {
var num = theform.original.value, rounded = theform.rounded
var with2Decimals = num.toString().match(/^-?\d+(?:\.\d{0,2})?/)[0]
rounded.value = with2Decimals
}
<form onsubmit="return calc(this)">
Original number: <input name="original" type="text" onkeyup="calc(form)" onchange="calc(form)" />
<br />"Rounded" number: <input name="rounded" type="text" placeholder="readonly" readonly>
</form>
The toFixed method fails in some cases unlike toString, so be very careful with it.
Update 5 Nov 2016
New answer, always accurate
function toFixed(num, fixed) {
var re = new RegExp('^-?\\d+(?:\.\\d{0,' + (fixed || -1) + '})?');
return num.toString().match(re)[0];
}
As floating point math in javascript will always have edge cases, the previous solution will be accurate most of the time which is not good enough.
There are some solutions to this like num.toPrecision, BigDecimal.js, and accounting.js.
Yet, I believe that merely parsing the string will be the simplest and always accurate.
Basing the update on the well written regex from the accepted answer by #Gumbo, this new toFixed function will always work as expected.
Old answer, not always accurate.
Roll your own toFixed function:
function toFixed(num, fixed) {
fixed = fixed || 0;
fixed = Math.pow(10, fixed);
return Math.floor(num * fixed) / fixed;
}
Another single-line solution :
number = Math.trunc(number*100)/100
I used 100 because you want to truncate to the second digit, but a more flexible solution would be :
number = Math.trunc(number*Math.pow(10, digits))/Math.pow(10, digits)
where digits is the amount of decimal digits to keep.
See Math.trunc specs for details and browser compatibility.
I opted to write this instead to manually remove the remainder with strings so I don't have to deal with the math issues that come with numbers:
num = num.toString(); //If it's not already a String
num = num.slice(0, (num.indexOf("."))+3); //With 3 exposing the hundredths place
Number(num); //If you need it back as a Number
This will give you "15.77" with num = 15.7784514;
Update (Jan 2021)
Depending on its range, a number in javascript may be shown in scientific notation. For example, if you type 0.0000001 in the console, you may see it as 1e-7, whereas 0.000001 appears unchanged (0.000001).
If your application works on a range of numbers for which scientific notation is not involved, you can just ignore this update and use the original answer below.
This update is about adding a function that checks if the number is in scientific format and, if so, converts it into decimal format. Here I'm proposing this one, but you can use any other function that achieves the same goal, according to your application's needs:
function toFixed(x) {
if (Math.abs(x) < 1.0) {
let e = parseInt(x.toString().split('e-')[1]);
if (e) {
x *= Math.pow(10,e-1);
x = '0.' + (new Array(e)).join('0') + x.toString().substring(2);
}
} else {
let e = parseInt(x.toString().split('+')[1]);
if (e > 20) {
e -= 20;
x /= Math.pow(10,e);
x += (new Array(e+1)).join('0');
}
}
return x;
}
Now just apply that function to the parameter (that's the only change with respect to the original answer):
function toFixedTrunc(x, n) {
x = toFixed(x)
// From here on the code is the same than the original answer
const v = (typeof x === 'string' ? x : x.toString()).split('.');
if (n <= 0) return v[0];
let f = v[1] || '';
if (f.length > n) return `${v[0]}.${f.substr(0,n)}`;
while (f.length < n) f += '0';
return `${v[0]}.${f}`
}
This updated version addresses also a case mentioned in a comment:
toFixedTrunc(0.000000199, 2) => "0.00"
Again, choose what fits your application needs at best.
Original answer (October 2017)
General solution to truncate (no rounding) a number to the n-th decimal digit and convert it to a string with exactly n decimal digits, for any n≥0.
function toFixedTrunc(x, n) {
const v = (typeof x === 'string' ? x : x.toString()).split('.');
if (n <= 0) return v[0];
let f = v[1] || '';
if (f.length > n) return `${v[0]}.${f.substr(0,n)}`;
while (f.length < n) f += '0';
return `${v[0]}.${f}`
}
where x can be either a number (which gets converted into a string) or a string.
Here are some tests for n=2 (including the one requested by OP):
0 => 0.00
0.01 => 0.01
0.5839 => 0.58
0.999 => 0.99
1.01 => 1.01
2 => 2.00
2.551 => 2.55
2.99999 => 2.99
4.27 => 4.27
15.7784514 => 15.77
123.5999 => 123.59
And for some other values of n:
15.001097 => 15.0010 (n=4)
0.000003298 => 0.0000032 (n=7)
0.000003298257899 => 0.000003298257 (n=12)
parseInt is faster then Math.floor
function floorFigure(figure, decimals){
if (!decimals) decimals = 2;
var d = Math.pow(10,decimals);
return (parseInt(figure*d)/d).toFixed(decimals);
};
floorFigure(123.5999) => "123.59"
floorFigure(123.5999, 3) => "123.599"
num = 19.66752
f = num.toFixed(3).slice(0,-1)
alert(f)
This will return 19.66
Simple do this
number = parseInt(number * 100)/100;
Just truncate the digits:
function truncDigits(inputNumber, digits) {
const fact = 10 ** digits;
return Math.floor(inputNumber * fact) / fact;
}
This is not a safe alternative, as many others commented examples with numbers that turn into exponential notation, that scenery is not covered by this function
// typescript
// function formatLimitDecimals(value: number, decimals: number): number {
function formatLimitDecimals(value, decimals) {
const stringValue = value.toString();
if(stringValue.includes('e')) {
// TODO: remove exponential notation
throw 'invald number';
} else {
const [integerPart, decimalPart] = stringValue.split('.');
if(decimalPart) {
return +[integerPart, decimalPart.slice(0, decimals)].join('.')
} else {
return integerPart;
}
}
}
console.log(formatLimitDecimals(4.156, 2)); // 4.15
console.log(formatLimitDecimals(4.156, 8)); // 4.156
console.log(formatLimitDecimals(4.156, 0)); // 4
console.log(formatLimitDecimals(0, 4)); // 0
// not covered
console.log(formatLimitDecimals(0.000000199, 2)); // 0.00
These solutions do work, but to me seem unnecessarily complicated. I personally like to use the modulus operator to obtain the remainder of a division operation, and remove that. Assuming that num = 15.7784514:
num-=num%.01;
This is equivalent to saying num = num - (num % .01).
I fixed using following simple way-
var num = 15.7784514;
Math.floor(num*100)/100;
Results will be 15.77
My version for positive numbers:
function toFixed_norounding(n,p)
{
var result = n.toFixed(p);
return result <= n ? result: (result - Math.pow(0.1,p)).toFixed(p);
}
Fast, pretty, obvious. (version for positive numbers)
The answers here didn't help me, it kept rounding up or giving me the wrong decimal.
my solution converts your decimal to a string, extracts the characters and then returns the whole thing as a number.
function Dec2(num) {
num = String(num);
if(num.indexOf('.') !== -1) {
var numarr = num.split(".");
if (numarr.length == 1) {
return Number(num);
}
else {
return Number(numarr[0]+"."+numarr[1].charAt(0)+numarr[1].charAt(1));
}
}
else {
return Number(num);
}
}
Dec2(99); // 99
Dec2(99.9999999); // 99.99
Dec2(99.35154); // 99.35
Dec2(99.8); // 99.8
Dec2(10265.985475); // 10265.98
The following code works very good for me:
num.toString().match(/.\*\\..{0,2}|.\*/)[0];
This worked well for me. I hope it will fix your issues too.
function toFixedNumber(number) {
const spitedValues = String(number.toLocaleString()).split('.');
let decimalValue = spitedValues.length > 1 ? spitedValues[1] : '';
decimalValue = decimalValue.concat('00').substr(0,2);
return '$'+spitedValues[0] + '.' + decimalValue;
}
// 5.56789 ----> $5.56
// 0.342 ----> $0.34
// -10.3484534 ----> $-10.34
// 600 ----> $600.00
function convertNumber(){
var result = toFixedNumber(document.getElementById("valueText").value);
document.getElementById("resultText").value = result;
}
function toFixedNumber(number) {
const spitedValues = String(number.toLocaleString()).split('.');
let decimalValue = spitedValues.length > 1 ? spitedValues[1] : '';
decimalValue = decimalValue.concat('00').substr(0,2);
return '$'+spitedValues[0] + '.' + decimalValue;
}
<div>
<input type="text" id="valueText" placeholder="Input value here..">
<br>
<button onclick="convertNumber()" >Convert</button>
<br><hr>
<input type="text" id="resultText" placeholder="result" readonly="true">
</div>
An Easy way to do it is the next but is necessary ensure that the amount parameter is given as a string.
function truncate(amountAsString, decimals = 2){
var dotIndex = amountAsString.indexOf('.');
var toTruncate = dotIndex !== -1 && ( amountAsString.length > dotIndex + decimals + 1);
var approach = Math.pow(10, decimals);
var amountToTruncate = toTruncate ? amountAsString.slice(0, dotIndex + decimals +1) : amountAsString;
return toTruncate
? Math.floor(parseFloat(amountToTruncate) * approach ) / approach
: parseFloat(amountAsString);
}
console.log(truncate("7.99999")); //OUTPUT ==> 7.99
console.log(truncate("7.99999", 3)); //OUTPUT ==> 7.999
console.log(truncate("12.799999999999999")); //OUTPUT ==> 7.99
Here you are. An answer that shows yet another way to solve the problem:
// For the sake of simplicity, here is a complete function:
function truncate(numToBeTruncated, numOfDecimals) {
var theNumber = numToBeTruncated.toString();
var pointIndex = theNumber.indexOf('.');
return +(theNumber.slice(0, pointIndex > -1 ? ++numOfDecimals + pointIndex : undefined));
}
Note the use of + before the final expression. That is to convert our truncated, sliced string back to number type.
Hope it helps!
truncate without zeroes
function toTrunc(value,n){
return Math.floor(value*Math.pow(10,n))/(Math.pow(10,n));
}
or
function toTrunc(value,n){
x=(value.toString()+".0").split(".");
return parseFloat(x[0]+"."+x[1].substr(0,n));
}
test:
toTrunc(17.4532,2) //17.45
toTrunc(177.4532,1) //177.4
toTrunc(1.4532,1) //1.4
toTrunc(.4,2) //0.4
truncate with zeroes
function toTruncFixed(value,n){
return toTrunc(value,n).toFixed(n);
}
test:
toTrunc(17.4532,2) //17.45
toTrunc(177.4532,1) //177.4
toTrunc(1.4532,1) //1.4
toTrunc(.4,2) //0.40
If you exactly wanted to truncate to 2 digits of precision, you can go with a simple logic:
function myFunction(number) {
var roundedNumber = number.toFixed(2);
if (roundedNumber > number)
{
roundedNumber = roundedNumber - 0.01;
}
return roundedNumber;
}
I used (num-0.05).toFixed(1) to get the second decimal floored.
It's more reliable to get two floating points without rounding.
Reference Answer
var number = 10.5859;
var fixed2FloatPoints = parseInt(number * 100) / 100;
console.log(fixed2FloatPoints);
Thank You !
My solution in typescript (can easily be ported to JS):
/**
* Returns the price with correct precision as a string
*
* #param price The price in decimal to be formatted.
* #param decimalPlaces The number of decimal places to use
* #return string The price in Decimal formatting.
*/
type toDecimal = (price: number, decimalPlaces?: number) => string;
const toDecimalOdds: toDecimal = (
price: number,
decimalPlaces: number = 2,
): string => {
const priceString: string = price.toString();
const pointIndex: number = priceString.indexOf('.');
// Return the integer part if decimalPlaces is 0
if (decimalPlaces === 0) {
return priceString.substr(0, pointIndex);
}
// Return value with 0s appended after decimal if the price is an integer
if (pointIndex === -1) {
const padZeroString: string = '0'.repeat(decimalPlaces);
return `${priceString}.${padZeroString}`;
}
// If numbers after decimal are less than decimalPlaces, append with 0s
const padZeroLen: number = priceString.length - pointIndex - 1;
if (padZeroLen > 0 && padZeroLen < decimalPlaces) {
const padZeroString: string = '0'.repeat(padZeroLen);
return `${priceString}${padZeroString}`;
}
return priceString.substr(0, pointIndex + decimalPlaces + 1);
};
Test cases:
expect(filters.toDecimalOdds(3.14159)).toBe('3.14');
expect(filters.toDecimalOdds(3.14159, 2)).toBe('3.14');
expect(filters.toDecimalOdds(3.14159, 0)).toBe('3');
expect(filters.toDecimalOdds(3.14159, 10)).toBe('3.1415900000');
expect(filters.toDecimalOdds(8.2)).toBe('8.20');
Any improvements?
Another solution, that truncates and round:
function round (number, decimals, truncate) {
if (truncate) {
number = number.toFixed(decimals + 1);
return parseFloat(number.slice(0, -1));
}
var n = Math.pow(10.0, decimals);
return Math.round(number * n) / n;
};
function limitDecimalsWithoutRounding(val, decimals){
let parts = val.toString().split(".");
return parseFloat(parts[0] + "." + parts[1].substring(0, decimals));
}
var num = parseFloat(15.7784514);
var new_num = limitDecimalsWithoutRounding(num, 2);
Roll your own toFixed function: for positive values Math.floor works fine.
function toFixed(num, fixed) {
fixed = fixed || 0;
fixed = Math.pow(10, fixed);
return Math.floor(num * fixed) / fixed;
}
For negative values Math.floor is round of the values. So you can use Math.ceil instead.
Example,
Math.ceil(-15.778665 * 10000) / 10000 = -15.7786
Math.floor(-15.778665 * 10000) / 10000 = -15.7787 // wrong.
Gumbo's second solution, with the regular expression, does work but is slow because of the regular expression. Gumbo's first solution fails in certain situations due to imprecision in floating points numbers. See the JSFiddle for a demonstration and a benchmark. The second solution takes about 1636 nanoseconds per call on my current system, Intel Core i5-2500 CPU at 3.30 GHz.
The solution I've written involves adding a small compensation to take care of floating point imprecision. It is basically instantaneous, i.e. on the order of nanoseconds. I clocked 2 nanoseconds per call but the JavaScript timers are not very precise or granular. Here is the JS Fiddle and the code.
function toFixedWithoutRounding (value, precision)
{
var factorError = Math.pow(10, 14);
var factorTruncate = Math.pow(10, 14 - precision);
var factorDecimal = Math.pow(10, precision);
return Math.floor(Math.floor(value * factorError + 1) / factorTruncate) / factorDecimal;
}
var values = [1.1299999999, 1.13, 1.139999999, 1.14, 1.14000000001, 1.13 * 100];
for (var i = 0; i < values.length; i++)
{
var value = values[i];
console.log(value + " --> " + toFixedWithoutRounding(value, 2));
}
for (var i = 0; i < values.length; i++)
{
var value = values[i];
console.log(value + " --> " + toFixedWithoutRounding(value, 4));
}
console.log("type of result is " + typeof toFixedWithoutRounding(1.13 * 100 / 100, 2));
// Benchmark
var value = 1.13 * 100;
var startTime = new Date();
var numRun = 1000000;
var nanosecondsPerMilliseconds = 1000000;
for (var run = 0; run < numRun; run++)
toFixedWithoutRounding(value, 2);
var endTime = new Date();
var timeDiffNs = nanosecondsPerMilliseconds * (endTime - startTime);
var timePerCallNs = timeDiffNs / numRun;
console.log("Time per call (nanoseconds): " + timePerCallNs);
Building on David D's answer:
function NumberFormat(num,n) {
var num = (arguments[0] != null) ? arguments[0] : 0;
var n = (arguments[1] != null) ? arguments[1] : 2;
if(num > 0){
num = String(num);
if(num.indexOf('.') !== -1) {
var numarr = num.split(".");
if (numarr.length > 1) {
if(n > 0){
var temp = numarr[0] + ".";
for(var i = 0; i < n; i++){
if(i < numarr[1].length){
temp += numarr[1].charAt(i);
}
}
num = Number(temp);
}
}
}
}
return Number(num);
}
console.log('NumberFormat(123.85,2)',NumberFormat(123.85,2));
console.log('NumberFormat(123.851,2)',NumberFormat(123.851,2));
console.log('NumberFormat(0.85,2)',NumberFormat(0.85,2));
console.log('NumberFormat(0.851,2)',NumberFormat(0.851,2));
console.log('NumberFormat(0.85156,2)',NumberFormat(0.85156,2));
console.log('NumberFormat(0.85156,4)',NumberFormat(0.85156,4));
console.log('NumberFormat(0.85156,8)',NumberFormat(0.85156,8));
console.log('NumberFormat(".85156",2)',NumberFormat(".85156",2));
console.log('NumberFormat("0.85156",2)',NumberFormat("0.85156",2));
console.log('NumberFormat("1005.85156",2)',NumberFormat("1005.85156",2));
console.log('NumberFormat("0",2)',NumberFormat("0",2));
console.log('NumberFormat("",2)',NumberFormat("",2));
console.log('NumberFormat(85156,8)',NumberFormat(85156,8));
console.log('NumberFormat("85156",2)',NumberFormat("85156",2));
console.log('NumberFormat("85156.",2)',NumberFormat("85156.",2));
// NumberFormat(123.85,2) 123.85
// NumberFormat(123.851,2) 123.85
// NumberFormat(0.85,2) 0.85
// NumberFormat(0.851,2) 0.85
// NumberFormat(0.85156,2) 0.85
// NumberFormat(0.85156,4) 0.8515
// NumberFormat(0.85156,8) 0.85156
// NumberFormat(".85156",2) 0.85
// NumberFormat("0.85156",2) 0.85
// NumberFormat("1005.85156",2) 1005.85
// NumberFormat("0",2) 0
// NumberFormat("",2) 0
// NumberFormat(85156,8) 85156
// NumberFormat("85156",2) 85156
// NumberFormat("85156.",2) 85156
Already there are some suitable answer with regular expression and arithmetic calculation, you can also try this
function myFunction() {
var str = 12.234556;
str = str.toString().split('.');
var res = str[1].slice(0, 2);
document.getElementById("demo").innerHTML = str[0]+'.'+res;
}
// output: 12.23
Here is what is did it with string
export function withoutRange(number) {
const str = String(number);
const dotPosition = str.indexOf('.');
if (dotPosition > 0) {
const length = str.substring().length;
const end = length > 3 ? 3 : length;
return str.substring(0, dotPosition + end);
}
return str;
}

Convert number to alphabet letter

I want to convert a number to its corresponding alphabet letter. For example:
1 = A
2 = B
3 = C
Can this be done in javascript without manually creating the array?
In php there is a range() function that creates the array automatically. Anything similar in javascript?
Yes, with Number#toString(36) and an adjustment.
var value = 10;
document.write((value + 9).toString(36).toUpperCase());
You can simply do this without arrays using String.fromCharCode(code) function as letters have consecutive codes. For example: String.fromCharCode(1+64) gives you 'A', String.fromCharCode(2+64) gives you 'B', and so on.
Snippet below turns the characters in the alphabet to work like numerical system
1 = A
2 = B
...
26 = Z
27 = AA
28 = AB
...
78 = BZ
79 = CA
80 = CB
var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
var result = ""
function printToLetter(number){
var charIndex = number % alphabet.length
var quotient = number/alphabet.length
if(charIndex-1 == -1){
charIndex = alphabet.length
quotient--;
}
result = alphabet.charAt(charIndex-1) + result;
if(quotient>=1){
printToLetter(parseInt(quotient));
}else{
console.log(result)
result = ""
}
}
I created this function to save characters when printing but had to scrap it since I don't want to handle improper words that may eventually form
Just increment letterIndex from 0 (A) to 25 (Z)
const letterIndex = 0
const letter = String.fromCharCode(letterIndex + 'A'.charCodeAt(0))
console.log(letter)
UPDATE (5/2/22): After I needed this code in a second project, I decided to enhance the below answer and turn it into a ready to use NPM library called alphanumeric-encoder. If you don't want to build your own solution to this problem, go check out the library!
I built the following solution as an enhancement to #esantos's answer.
The first function defines a valid lookup encoding dictionary. Here, I used all 26 letters of the English alphabet, but the following will work just as well: "ABCDEFG", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", "GFEDCBA". Using one of these dictionaries will result in converting your base 10 number into a base dictionary.length number with appropriately encoded digits. The only restriction is that each of the characters in the dictionary must be unique.
function getDictionary() {
return validateDictionary("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
function validateDictionary(dictionary) {
for (let i = 0; i < dictionary.length; i++) {
if(dictionary.indexOf(dictionary[i]) !== dictionary.lastIndexOf(dictionary[i])) {
console.log('Error: The dictionary in use has at least one repeating symbol:', dictionary[i])
return undefined
}
}
return dictionary
}
}
We can now use this dictionary to encode our base 10 number.
function numberToEncodedLetter(number) {
//Takes any number and converts it into a base (dictionary length) letter combo. 0 corresponds to an empty string.
//It converts any numerical entry into a positive integer.
if (isNaN(number)) {return undefined}
number = Math.abs(Math.floor(number))
const dictionary = getDictionary()
let index = number % dictionary.length
let quotient = number / dictionary.length
let result
if (number <= dictionary.length) {return numToLetter(number)} //Number is within single digit bounds of our encoding letter alphabet
if (quotient >= 1) {
//This number was bigger than our dictionary, recursively perform this function until we're done
if (index === 0) {quotient--} //Accounts for the edge case of the last letter in the dictionary string
result = numberToEncodedLetter(quotient)
}
if (index === 0) {index = dictionary.length} //Accounts for the edge case of the final letter; avoids getting an empty string
return result + numToLetter(index)
function numToLetter(number) {
//Takes a letter between 0 and max letter length and returns the corresponding letter
if (number > dictionary.length || number < 0) {return undefined}
if (number === 0) {
return ''
} else {
return dictionary.slice(number - 1, number)
}
}
}
An encoded set of letters is great, but it's kind of useless to computers if I can't convert it back to a base 10 number.
function encodedLetterToNumber(encoded) {
//Takes any number encoded with the provided encode dictionary
const dictionary = getDictionary()
let result = 0
let index = 0
for (let i = 1; i <= encoded.length; i++) {
index = dictionary.search(encoded.slice(i - 1, i)) + 1
if (index === 0) {return undefined} //Attempted to find a letter that wasn't encoded in the dictionary
result = result + index * Math.pow(dictionary.length, (encoded.length - i))
}
return result
}
Now to test it out:
console.log(numberToEncodedLetter(4)) //D
console.log(numberToEncodedLetter(52)) //AZ
console.log(encodedLetterToNumber("BZ")) //78
console.log(encodedLetterToNumber("AAC")) //705
UPDATE
You can also use this function to take that short name format you have and return it to an index-based format.
function shortNameToIndex(shortName) {
//Takes the short name (e.g. F6, AA47) and converts to base indecies ({6, 6}, {27, 47})
if (shortName.length < 2) {return undefined} //Must be at least one letter and one number
if (!isNaN(shortName.slice(0, 1))) {return undefined} //If first character isn't a letter, it's incorrectly formatted
let letterPart = ''
let numberPart= ''
let splitComplete = false
let index = 1
do {
const character = shortName.slice(index - 1, index)
if (!isNaN(character)) {splitComplete = true}
if (splitComplete && isNaN(character)) {
//More letters existed after the numbers. Invalid formatting.
return undefined
} else if (splitComplete && !isNaN(character)) {
//Number part
numberPart = numberPart.concat(character)
} else {
//Letter part
letterPart = letterPart.concat(character)
}
index++
} while (index <= shortName.length)
numberPart = parseInt(numberPart)
letterPart = encodedLetterToNumber(letterPart)
return {xIndex: numberPart, yIndex: letterPart}
}
this can help you
static readonly string[] Columns_Lettre = new[] { "A", "B", "C"};
public static string IndexToColumn(int index)
{
if (index <= 0)
throw new IndexOutOfRangeException("index must be a positive number");
if (index < 4)
return Columns_Lettre[index - 1];
else
return index.ToString();
}

javascript splitting a var that is numbers and letters

I'd prefer to not use regex, but if needed, so be it.
I have some code and I want to take a user's input and check to make sure that it is an isbn 10. In other words it must be a 10 digit number or a 9 digit number with an x at the end (the x represents the number 10). For my purposes, I'd like to turn the users input into an array of each digit. If there is an x I'd like to change that into a 10. I am having trouble doing this! I have seen other questions that are somewhat similar and they all use regex. Like I said, I'd prefer to not use regex, but if need be...
<h1>Problem #3:</h1>
<form name= "form">
<input id= "input" name= "isbn" type="number" placeholder="Enter your ISBN-10" min="0" />
<input id= "button" type="button" name="Validate" value="Validate" />
</form>
<div id="validISBN">
Valid ISBN
</div>
<div id="invalidISBN">
Invalid ISBN
</div>
<script src="js/jquery-2.0.3.min.js"></script>
<script>
$( document ).ready(function() {
alert("Welcome to ISBN Validator!");
//Add the event listener for the validate button here
//Look at toggling the CSS display property based on the result
$("#button").click(function(){
checker(document.form.isbn.value);
});
});
var checker = function(isbn){
isbn = isbn.toString().split('');
if (isbn[9] == 'x'|| isbn[9] == 'X') {
isbn[9] = 10;
}
if (isbn.length !== 10) {
alert("invalid ISBN!" + isbn.length);
}
else{
var sum = 0;
for (var x=10; x>0; x--){
sum += x*isbn[10-x];
}
alert("FINAL!!" + sum%11);
}
}
Input: 0375726721
Output: FINAL!!0
:Works
Input:067978330X
Expected Output: FINAL!!0
Actual Output: Invalid ISBN!0
:Does not work!
var isbn = '074759582x';
if (!/^\d{9}(\d|x)$/i.test(isbn)) // validation with regexp
alert('Invalid ISBN');
else {
var arr = isbn.split('');
arr[9] = arr[9].toLowerCase() == 'x' ? 10 : arr[9]; // replacement of x by 10
// below is your summation, just performed in another way.
var total = arr.map(function(el, index, arr) {
return (index + 1) * arr[10 - index - 1];
}).reduce(function(a, b) {return a + b;});
alert(total % 11);
}
Done
var isbn = '074759582x';
Split the string into characters using split. Apply map to grab the x and convert it to 10 if necessary. Then map each character to a number
array = isbn
.split('')
.map(function(char, i) {
return i === 9 && char.toLowerCase() === 'x' ? 10 : char;
})
.map(Number)
;
The ISBN is valid if it's of length 10, and there are no NaNs in it.
valid = array.length === 10 && !array.some(isNaN);
Checksum uses reduce, as in another answer:
sum = array.reduce(function(result, v, i) {
return result + (10-i) * v;
}, 0) % 11;
Problem #3:
<form name= "form">
<input id= "input" name= "isbn" type="number" placeholder="Enter your ISBN-10" min="0" />
<input id= "button" type="button" name="Validate" value="Validate" onclick = "checker()" />
</form>
<div id="validISBN">
Valid ISBN
</div>
<div id="invalidISBN">
Invalid ISBN
</div>
<script>
function checker () {
isbn = document.form.isbn.value;
isbn = isbn.toString().split('');
if (isbn[9] == 'x' || isbn[9] == 'X') {
isbn[9] = 10;
}
if (isbn.length !== 10) {
alert("invalid ISBN!" + isbn.length);
}
else {
var sum = 0;
for (var x = 10; x > 0; x--) {
sum += x * isbn[10 - x];
}
alert("FINAL!!" + sum % 11);
}
}
</script>

Categories