total array value, keep decimal points - javascript

I want to calculate a total from the values in an array.
I've tried several different approaches, but starting to struggle with the wonders of number calculations in JS.
As an example, this is my array:
["0.20", "1.20"]
and how i've been trying to get a total from these values:
var totalPrice = 0;
var arrLength = arr.length;
while(arrLength--)
totalPrice += parseFloat(Math.round(arr[arrLength] * 100) / 100).toFixed(2);
However, this returns 01.200.20.
If I modify the array to have only one value, 0.20, this returns 00.20.
How can I get a total value from the array that will retain the decimal places?
JSFiddle
FYI - the fiddle also contains some objects which generate the array, if an item is set to true.

You are doing string concatenation instead of adding the floats. Just use the parseFloat, then get your decimal places at the end when you need the actual string representation.
var arr = ["0.20", "1.20"];
var totalPrice = 0;
var arrLength = arr.length;
while (arrLength--) {
totalPrice += parseFloat(arr[arrLength]);
}
document.getElementById("result").innerHTML = totalPrice.toFixed(2);
<div id="result">x</div>

Related

Separating a string into integers and storing sum and averages

JavaScript; I want to get the values in a string which always has the following format but also has an indeterminate number of variables:
Sample String "340=5;339=5;338=3;337=4;336=1;335=4;334=4;333=4"
The variables named as 340, 339, 338 etc. in this string store integer values such as 5, 4, 1 and so on. I want to extract the integer values for each of the variables (extracting what's after the equal signs) and store the sum and average value of them in two separate variables as "sum" and "avr".
Nothing fancy, hopefully nice and readable.
function calculate(myString) {
var values = myString.split(';');
var sum = 0;
values.forEach(function(el, i) {
sum += parseInt(el.split('=')[1]);
});
return {
sum: sum,
avg: sum / values.length
}
}
var results = calculate("340=5;339=5;338=3;337=4;336=1;335=4;334=4;333=4");
console.log(results.sum); // => 30
console.log(results.avg); // => 3.75
As you have a simple pattern, you can use a RegExp to find the bits of interest. Here is an example using String.prototype.split and Array.prototype.reduce
var str = "340=5;339=5;338=3;337=4;336=1;335=4;334=4;333=4";
var parts = (';'+str).split(/;\d+=/).slice(1), // passing the RegExp to .split
sum = parts.reduce(function(prev, cur) {
return prev + +cur; // notice String cur to Number
}, 0),
avr = sum / parts.length; // assuming you want mean average
console.log(sum, avr); // 30 3.75
I would split the string then loop through all the values to get the sum and average.
var str="340=5;339=5;338=3;337=4;336=1;335=4;334=4;333=4";
var array =str.split(/;?\d+=/g);
var sum=0;
for(i=0;i<array.length;i++){
if(!isNaN(parseInt(array[i])))
sum+=parseInt(array[i]);
else{
array.splice(i,1);
i--;
}
}
console.log(sum);
console.log(sum/array.length);
This is trivial string evaluation. The only method you need is split, and the only logic you need is a for loop.
var values = "340=5;339=5;338=3;337=4;336=1;335=4;334=4;333=4";
var sum = []
var avr = []
values = values.split(';');
for(i=0; i<values.length; i++){
numbers = values[i].split('=')
sum.push(numbers[0])
avr.push(numbers[1])
}

sum of uint8array javascript

I'm trying to sum and then average a stream of data, some code here.
var getAverage = function(dataArray){
var total,
sample = dataArray.length,
eArray = Array.prototype.slice.call(dataArray);
for (var i = 0; i< sample; i++) {
total+= eArray[i];
}
return total;
}
var output = function(){
//source data
var dataArray = new Uint8Array(bufferLength);
analyser.getByteTimeDomainData(dataArray);
var average = getAverage(dataArray);
$('#average').text(average);
window.requestAnimationFrame(output);
Every element in the array returns a number, but it still returns NaN. Help?
Set total = 0; currently it is defaulting to undefined. undefined + a number = NaN, and NaN + a number = NaN.
The declared variable total is undefined which means it will create NaN (Not-a-Number) when a number is added to it.
Also, Typed Array (ArrayBuffer/views) and Array are not the same, and converting a typed array to an ordinary Array is making iteration slower as typed arrays are actual byte-buffers while Arrays are (node) lists. That on top of the cost of conversion itself.
Just add them straight forward. Remember to divide the sum on length and of course to initialize total:
var getAverage = function(dataArray){
var total = 0, // initialize to 0
i = 0, length = dataArray.length;
while(i < length) total += dataArray[i++]; // add all
return length ? total / length : 0; // divide (when length !== 0)
}

Is this is a good way to generate a secure random string in JavaScript?

Below is some code I wrote to generate a random string in JavaScript. Are there any security issues if I use the values received from this method as salts or tokens for users?
String.random = function(length, characters) {
length = length === undefined ? 32 : length;
characters = characters === undefined ? 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' : characters;
var maxIndex = characters.length - 1;
var string = '';
for(var i = 0; i < length; i++) {
string += characters[Number.random(0, maxIndex)];
}
return string;
}
You can use crypto.getRandomValues() to get cryptographically secure random numbers in javascript, but they're not decimal numbers like Math.random(), so it takes more work to deal with them. Here's the plain javascipt solution with crypto.getRandomValues():
function getCryptoRandomBetween(min, max){
//the highest random value that crypto.getRandomValues could store in a Uint32Array
var MAX_VAL = 4294967295;
//find the number of randoms we'll need to generate in order to give every number between min and max a fair chance
var numberOfRandomsNeeded = Math.ceil((max - min) / MAX_VAL);
//grab those randoms
var cryptoRandomNumbers = new Uint32Array(numberOfRandomsNeeded);
crypto.getRandomValues(cryptoRandomNumbers);
//add them together
for(var i = 0, sum = 0; i < cryptoRandomNumbers.length; i++){
sum += cryptoRandomNumbers[i];
}
//and divide their sum by the max possible value to get a decimal
var randomDecimal = sum / (MAX_VAL * numberOfRandomsNeeded);
//if result is 1, retry. otherwise, return decimal.
return randomDecimal === 1 ? getCryptoRandomBetween(min, max) : Math.floor(randomDecimal * (max - min + 1) + min);
}
function getRandomChar(str){
return str.charAt(getCryptoRandomBetween(0, str.length - 1));
}
String.random = function(length, characters) {
for(var i = 0, str = ""; i < length; i++) str += getRandomChar(characters);
return str;
};
console.log(String.random(60, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"));
Pretty rough on the eyes, but it works. If you want a simpler solution, my preference is rando.js. it works for plain javascript as well as Node.js/React. You can use rando(str) to get a random character from a string, so building a random string the way you want is as simple as:
String.random = function(length, characters) {
for(var i = 0, str = ""; i < length; i++) str += rando(characters);
return str;
};
console.log(String.random(60, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"));
<script src="https://randojs.com/2.0.0.js"></script>
Let me reiterate that the strings both of these solutions generate have enough entropy to be safe for use as passwords, salts, or tokens for users.
I think it all reduces to finding an alternative way to generate random numbers in Javascript, not relying on Math.random.
Once you have an alternative to Math.random, you can generate your random string in an almost identical way. I suggest to have a look at the Mersenne twister algorithm. There are quite a few Javascript implementations around (some are even in the Wikipedia page I linked).
Like many random number generators, you have to start with a seed: you can generate one with Math.random, adding an additional "salt" if you like.
Using crypto library to generate random string in NodeJs
import { randomBytes } from 'crypto';
function random(length) {
return randomBytes(Math.ceil(length / 2)).toString('hex').slice(0, length);
}
const randomString = random(10);
Using crypto.getRandomValues you can easily generate a secure random identifier:
function genId(){
let array = new Uint8Array(16);
crypto.getRandomValues(array);
return btoa(array);
}

find the mean of an array of 1000 random integers javascript

I am having trouble with calculating the mean value of an array of 1000 random numbers. The array holds 1000 random number between 1 and 30.
I also want to be able to count how many of each number occurred in the array and print the amount of each number in a frequency distribution table.
<script type = "text/javascript">
var arr = [];
function getRandom( num ){
return Math.round(Math.random() * num)+1;
}
for (var i = 0; i < 1000; i++) {
arr.push(getRandom( 30 ));
}
document.write(arr);
document.write("<br/>");
for (var i = 0; i <= 1000; i++){
sum += parseInt(arr[i]);
}
var mean = sum/arr.length;
document.write("The sum of all the elements is: " + sum + " The mean is: " + mean);
</script>
You don't have to run the cycle twice. Do everything on the fly:
var distrTable = {};
for (var i = 0; i < 1000; i++) {
var rnd = getRandom(30);
sum += rnd;
arr.push(rnd);
if (!distrTable[rnd]) {
distrTable[rnd] = 0;
}
distrTable[rnd]++;
}
Now the variables contain the following information:
arr - all random numbers.
distrTable - each random number with frequency.
sum - the sum of all random numbers.
jsFiddle example
By the way, if you're wondering why your code is not working... Here are the reasons:
First of define the variable sum. Before the loop just put sum = 0;
Second of all, while the array is long 1000 items, in the second for you loop for 1001 times. The declaration should be as follows:
for (var i = 0; i < 1000; i++) // not i <= 1000;
Then the code should work.
The trivial error in your code is that in your second loop you are running up to element 1001 instead of element 1000.
Since that element is undefined, it causes a sum of NaN and the mean, likewise.
To fix, change the <= 1000 to just < 1000
You should also remove the parseInt call - that's only necessary if your input values are strings, but your array already contains numbers.
Beware when you generate random numbers like this:
function getRandom( num ){
return Math.round(Math.random() * num)+1;
}
... this code can generate numbers from 1 to 31! It's because of the Math.round -- if Math.random() generates 0.99, 0.99 * 30 will equal 29.7, that will be rounded to 30, and then 1 will be added!
The solution is to replace Math.round with Math.floor.

How to get a unique random integer in a certain range for every number in that range in javascript?

I have:
function getRandomInt(min, max){
return Math.floor(Math.random() * (max - min + 1)) + min;
}
But the problem is I want randomise the population of something with elements in an array (so they do not appear in the same order every time in the thing I am populating) so I need to ensure the number returned is unique compared to the other numbers so far.
So instead of:
for(var i = 0; i < myArray.length; i++) {
}
I have:
var i;
var count = 0;
while(count < myArray.length){
count++;
i = getRandomInt(0, myArray.length); // TODO ensure value is unique
// do stuff with myArray[i];
}
It looks like rather than independent uniform random numbers you rather want a random permutation of the set {1, 2, 3, ..., N}. I think there's a shuffle method for arrays that will do that for you.
As requested, here's the code example:
function shuffle(array) {
var top = array.length;
while (top--) {
var current = Math.floor(Math.random() * top);
var tmp = array[current];
array[current] = array[top - 1];
array[top - 1] = tmp;
}
return array;
}
Sometimes the best way to randomize something (say a card deck) is to not shuffle it before pulling it out, but to shuffle it as you pull it out.
Say you have:
var i,
endNum = 51,
array = new Array(52);
for(i = 0; i <= endNum; i++) {
array[i] = i;
}
Then you can write a function like this:
function drawNumber() {
// set index to draw from
var swap,
drawIndex = Math.floor(Math.random() * (endNum+ 1));
// swap the values at the drawn index and at the "end" of the deck
swap = array[drawIndex];
array[drawIndex] = array[endNum];
array[endNum] = swap;
endNum--;
}
Since I decrement the end counter the drawn items will be "discarded" at the end of the stack and the randomize function will only treat the items from 0 to end as viable.
This is a common pattern I've used, I may have adopted it into js incorrectly since the last time I used it was for writing a simple card game in c#. In fact I just looked at it and I had int ____ instead of var ____ lol
If i understand well, you want an array of integers but sorted randomly.
A way to do it is described here
First create a rand function :
function randOrd(){
return (Math.round(Math.random())-0.5); }
Then, randomize your array. The following example shows how:
anyArray = new Array('1','2','3','4','5');
anyArray.sort( randOrd );
document.write('Random : ' + anyArray + '<br />';);
Hope that will help,
Regards,
Max
You can pass in a function to the Array.Sort method. If this function returns a value that is randomly above or below zero then your array will be randomly sorted.
myarray.sort(function() {return 0.5 - Math.random()})
should do the trick for you without you having to worry about whether or not every random number is unique.
No loops and very simple.

Categories