This question already has answers here:
Is floating point math broken?
(31 answers)
Closed last year.
My problem is a wrong result.
I have a function this function has a distance and a time.
The result I want to achieve is calculating running speed.
function runningPace(distance, time) {
let result = time.replace(":", ".")
let fl = parseFloat(result)
let calc = fl / distance
let num = calc.toFixed(2) + ''
if(num.length === 1) {
num = num + '.00'
}
let rep = num.replace('.', ':')
console.log(distance, time, result, fl, calc, rep, num)
return rep;
}
console.log(runningPace(5, '25:00')) // '5:00'
console.log(runningPace(4.99, '22:32')) // '4:30'
I wrote such a function. Sorry for the naming, I'll fix it when I get it fixed.
When I test this code, the output is:
expected '4:47' to equal '4:30'
'4:30' => four minute thirty second
How can I find a solution? Thanks everyone in advance.
convert anything in seconds:
function runningPace(dist, time)
{
let
[ mn, sc ] = time.split(':').map(Number)
, fl = Math.floor(((mn *60) + sc) / dist)
;
sc = fl % 60
mn = (fl - sc) / 60
return `${mn}:${(sc<9)?'0'+sc:sc}`
}
console.log(runningPace( 5, '25:00')) // 5:00
console.log(runningPace( 4.99, '22:32')) // 4:30
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
In javascript I'm looking to complete one numbers, you can help me generate a array of please.
The first 4 digits start by "23 29 xx xx xx", the xx remains to be completed with a range from 0 to 99. Ex. 23 29 01 02 03
let firstDigit = "2329";
let numberOfRandomDigit = "6";
let firstRange = "01";
let maxRange = "99";
let arrayOfNumbers = ["2329010203, 2329xxxxxx", ...];
I don't know to do this with a loop for complete array
as I see it's a 10 digit number, and you know 4 digits initial, so rest 6 digits you can generate randomly like this :
from random import randint
def random_num(n):
range_start = 10**(n-1)
range_end = (10**n)-1
return randint(range_start, range_end)
rest_digit = random_num(6)
Now you can simply append these 6 digit to the 4 digits that you have.
In JavaScript:
let firstDigit = "2329";
let firstRange = "00";
let maxRange = "99";
var random_string = function(digits) {
var num = Math.floor(Math.random() * (maxRange-firstRange+1)+firstRange).toString();
while (num.length < digits)
{
num = "0" + num;
}
return num;
}
var arrayOfNumbers = [];
for (i=0;i<10;i++)
{
six_digit_string = random_string(2)+random_string(2)+random_string(2);
arrayOfNumbers.push(firstDigit+six_digit_string);
}
In Python:
import random
def random_two_digit_numbers():
return str(random.randint(0,99)).zfill(2)
generated_string = '23 29 {} {} {}'.format(random_two_digit_numbers,random_two_digit_numbers,random_two_digit_numbers)
I have a floating point number (for example): 0.004178174922295
How could I get the decremental function to make a calculations from this number to 0 in specific amount of time (for example 1 second)?
Thanks.
Expected values:
0.004178174922295
0.004178174922294
0.004178174922293
...
0
As raina77ow and others pointed out in the comments, operations with decimal numbers are problematic in JS, approximations are made and the results may be inexact.
A workaround would be turn the infinitesimals into big integral numbers, work with them and convert them back at the end.
Is this what you were looking for? Please let me know.
EDIT
You can ask for the countdown to be done in a certain amount of time, it does work with reasonable numbers, but in Javascript the minimum interval is of 10 milliseconds, you can't call intervals shorter than that. With the example number you gave, 0.004178174922295, it's like counting down from 4178174922295 to zero. That would requiere almost 1325 years in 10 millisecond intervals (if my math is correct, either way I expect you were going to pass a much shorter lapse).
function infinitesimalCountDown(num, seconds) {
// I create a coeficient to convert the decimal to an int
// Will be a big number starting with "1" and followed by a bunch of zeroes
let coefString = '1';
for(let i=0; i<num.toString().length-2; i++) {
coefString += '0';
}
const coef = Number(coefString);
// This has the digits from the original original but it's an int
let counter = Math.round(num*coef);
// Now I can just treat it as an int and convert it back for the output
const icdInterval = setInterval(() => {
counter--;
console.log(counter/coef);
if(counter <= 0) clearInterval(icdInterval);
}, Math.round(seconds*1000/counter));
}
console.log("It works with a short number");
infinitesimalCountDown(0.0041, 10);
setTimeout(() => {
console.log("It doesn't work with a long number");
infinitesimalCountDown(0.004178174922295, 3000);
}, 12 * 1000);
If you are fine with the steps being the necessary for Javascript to be able to process it, you can do the following:
function infinitesimalCountDown(num, seconds) {
let coefString = '1'
for(let i=0; i<num.toString().length-2; i++) {
coefString += '0'
}
const coef = Number(coefString)
let counter = Math.round(num*coef)
let steps = seconds * 1000 / counter
steps = steps < 100 ? 100 : steps
let step = 1
if(steps == 100) {
step = counter / ((seconds * 1000) / steps)
}
console.log(step)
const icdInterval = setInterval(() => {
counter -= step;
if(counter <= 0) {
counter = 0
clearInterval(icdInterval)
}
console.log(counter/coef)
}, steps)
}
infinitesimalCountDown(0.004178174922295, 5)
If you can represent the input number as number type (so not have many decimals), you can do this using normal number subtraction.
Here, the important thing is to get the unit to be subtracted. You can get the unit using Math.pow.
And from this floating point guide, it is needed to round the counted number and that can be done using toFixed function.
let input = 0.004178174922295;
const decimalCount = input.toString().length - 2;
const unit = Math.pow(10, -1 * decimalCount);
console.log(input);
const loopInterval = setInterval(() => {
input = Number((input - unit).toFixed(decimalCount));
console.log(input);
if (input == 0) {
clearInterval(loopInterval);
}
}, 1000);
And if the input number has many decimals so it is received as string type (not able to present using number type), it is needed to do the subtraction using string as follows.
const input = '0.0041781749222934534534534535';
const inputArr = input.split('.');
const intNum = inputArr[0]; // Present integer
let decimals = inputArr[1]; // Present decimals after '.'
const unit = 1;
function replaceAt(str, index, replace) {
return str.substring(0, index) + replace + str.substring(index + 1);
}
console.log(input);
const loopInterval = setInterval(() => {
let index = decimals.length - 1;
while (parseInt(decimals[index]) < unit) {
decimals = replaceAt(decimals, index --, '9');
}
decimals = replaceAt(decimals, index, `${parseInt(decimals[index]) - unit}`);
console.log(`${intNum}.${decimals}`);
}, 1000);
I have an array of time duration strings as below, and would like to find the minimum time.
group = ["41:04", "54:50", "01:03:50"] // note this is mix of **mm:ss** and **HH:mm:ss**
I am using moment:
group.map(tid => moment.duration(tid,'hh:mm:ss').asSeconds());
but it interprets the first two elements as "hh:mm" instead of "mm:ss", and results in:
[147840, 197400, 3830]
However, the first element "41:04" is the shortest time duration.
Is there any way to get this right using moment? Or what is the best way to find the minimum time duration?
Note that if i concatenate zeros to the string by myself (ie, 00:41:04), it will be correct.
You could calculate the seconds elapsed using simple mathematics without using any libraries.
For example;
41:04 = 41 * 60 + 04
01:03:50 = 01 * (60 ^ 2) + 03 * 60 + 50
Creating simple function to calculate seconds elapsed.
const getSeconds = str => {
const sp = str.split(":");
let sum = 0;
sp.map((d, k) => {
sum += Number(d) * 60 ** (sp.length - 1 - k);
});
return sum;
};
Now you could loop through your array to get the seconds.
const min = group.reduce((d, k) => {
const a = getSeconds(d),
b = getSeconds(k);
return a < b ? d : k;
});
As a whole you could check out the code snippet below;
const group = ["50:04","41:04", "54:50", "01:03:50"];
const getSeconds = str => {
const sp = str.split(":");
let sum = 0;
sp.map((d, k) => {
sum += Number(d) * 60 ** (sp.length - 1 - k);
});
return sum;
};
const min = group.reduce((d, k) => {
const a = getSeconds(d),
b = getSeconds(k);
return a < b ? d : k;
});
console.log(min);
There might be more elegant solutions. But this is what I came up with. :D
This question already has answers here:
JavaScript: How to reverse a number?
(19 answers)
Closed 3 years ago.
Can anyone show me where I'm going wrong in my code please? I'm trying to reverse a number without changing it to a string. I've been searching google and looked through the previous questions asked about this topic and from what I can see my code mirrors the other answers.
I've only been able to find code in Java, C, or C++ that do not use the to string method.
In my attempts, when I run the code in the browser console it either gives me an answer of "Infinity" or crashes my browser.
Here's my code...
function reverseNumber(number) {
var revNumber = 0;
while (number > 0) {
revNumber = (revNumber * 10) + (number % 10);
number = number / 10;
}
return revNumber;
}
console.log(reverseNumber(876));
I know it must be some small syntax error but I just don't see it. Any insight would be appreciated. Thanks!
number = number / 10; inside a while loop whose condition is number > 0 means that number will only reach 0 after a very large number of iterations, once number precision fails. (eg. 876 => 87.6 => 8.76 => .876 => .0876...) That's not what you want. You might divide by 10 and drop the decimal part:
function reverseNumber(number) {
var revNumber = 0;
while (number > 0) {
revNumber = (revNumber * 10) + (number % 10);
number = Math.floor(number / 10);
}
return revNumber;
}
console.log(reverseNumber(876));
These works.
Basic Implementation:
function reverse(n)
{
var temp=0;
while(n)
{
temp *= 10;
temp += n%10;
n = Math.floor(n/10);
}
return temp;
}
console.log(reverse(123))
console.log(reverse(456))
console.log(reverse(789))
console.log(reverse(7890))
Inline Basic implementation:
function reverse(n)
{
var reverse=0;
while(n>0) (reverse=reverse*10+n%10, n=Math.floor(n/10));
return reverse;
}
console.log(reverse(123))
console.log(reverse(456))
console.log(reverse(789))
console.log(reverse(7890))
Implementation using arrays.
function reverse(n)
{
var arr=[], reverse=0;
while(n>0) (arr.push(n%10), n=Math.floor(n/10));
while(arr.length) reverse=reverse*10+arr.shift();
return reverse;
}
console.log(reverse(123))
console.log(reverse(456))
console.log(reverse(789))
console.log(reverse(7890))
number = Math.floor(number / 10);
You need to Math.floor as number = number / 10; will give in floating points value which will always be greater than 0
function reverseNumber(number) {
var revNumber = 0;
console.log("######### steps ###########");
while (number > 0) {
console.log("Step " , number);
revNumber = (revNumber * 10) + (number % 10);
number = Math.floor(number / 10);
}
console.log("######### steps End ###########");
return revNumber;
}
console.log(reverseNumber(876));
function reverseNumber(number) {
var revNumber = 0;
while (number > 0) {
revNumber = (revNumber * 10) + (number % 10);
number = Math.floor(number / 10);
}
return revNumber;
}
console.log(reverseNumber(876));
El problema estaba en la reeasignaciĆ³n del valor del number, con el Math.floor sacamos la parte entera y solo esta, asi evitamos los decimales.
function reverseInt(int) {
return parseInt(int.toString().split('').reverse().join(''))
}
console.log(reverseInt(510));
This is my array. Its length is about 9000. This is what a small bit of it looks like:
foreach_arr = ["21:07:01.535", "21:07:01.535", "21:07:26.113"]
There are a few occurences where the times diff is greater than a minute, and that is when I want to grab those times. And later use those times to get certain indices from another array. i.e "array"
I'm also using moment.js for time parsing.
Expected result: array = [8127, 9375, 13166, 14182]
Actual result: array = [8127, 13166]
Can't seem to find the issue here, I am getting 2 results when im supposed to be getting 4.
If the whole array is needed for troubleshooting, ill add it if I can.
var xx = foreach_arr.length - 1;
for(var z = 0; z < xx; z++) {
var current_row = foreach_arr[z];
var next_row = foreach_arr[z + 1];
var msElapsedTime = moment(next_row,"HH:mm:ss.SSS").diff(moment(current_row, "HH:mm:ss.SSS")) / 1000;
if(msElapsedTime > 60) {
attempt_indices.push(foreach_arr[z]);
}
}
for(var x = 0; x < attempt_indices.length; x++) {
array.push(newdata.indexOf(attempt_indices[x]));
}
Since the OP doesn't really need my code anymore, I'm posting it here to remove the downvote as much as anything else :)
const foreach_arr = ["21:07:01.535", "21:07:01.535", "21:07:26.113", '22:01:01.000'];
let processedForeach_arr = [];
let gtOneMinuteDiff = [];
foreach_arr.forEach((elem1, index1) => {
// elem1.split(':') turns foreach_arr[0] into ['21', '07', '01.535']
const splitElementArray = elem1.split(':');
let timeInMs = 0;
// this changes ['21', '07', '01.535'] into [75600000, 420000, 1535]
splitElementArray.forEach((elem2, index2) => {
if (index2 === 0) { // elem2 is hours. 3.6M ms per hour.
timeInMs += parseFloat(elem2) * 60 * 60 * 1000;
} else if (index2 === 1) { // elem2 is minutes. 60K ms per minute.
timeInMs += parseFloat(elem2) * 60 * 1000;
} else if (index2 === 2) { // elem2 is seconds. 1K ms per second.
timeInMs += parseFloat(elem2) * 1000;
} else {
throw `Expected array element formatted like HH:MM:SS.ms. Error on
element ${elem1}.`;
}
});
processedForeach_arr.push(timeInMs);
let timeDiff = processedForeach_arr[index1 - 1] - processedForeach_arr[index1];
if (Math.abs(timeDiff) > 60000) {
gtOneMinuteDiff.push(timeDiff);
}
});
To get the difference in milliseconds between foreach_arr[n] and foreach_arr[n+1], this code will
split each element of foreach_arr into 3 strings (hours, minutes, and seconds + milliseconds)
run parseFloat on each of those values to convert them to a number
convert all numbers to milliseconds and add them together
compare each consecutive value and return the difference.
Ok, I got this far and my son needs me. I'll finish out the code asap but you might beat me to it, hopefully the instructions above help.
turns out my code wasn't wrong. Just my idea of the whole proccess.
array = [8127, 13166]
is what I initialy get. With this, I use indexOf on my other array to eventually get my array as expected:
var another_test_arr = [];
for(var v = 0; v < array.length ; v++) {
var find = foreach_arr.indexOf(attempt_indices[v]);
another_test_arr.push(array[v], newdata.indexOf(foreach_arr[find + 1]));
}
Result: array = [8127, 9375, 13166, 14182]