javascript nodejs rounding errors - javascript

i want everything to be precise and add up exactly and i can't allow the total to be a penny off.
var buy_amount = 132.32000000; //amount in bitcoin
var buy_amount_satoshi = buy_amount*100000000; //amount in satoshi
var sell_rate = 10.00000000; //USD rate
var spend_usd = buy_amount_satoshi*sell_rate; //total USD
var spend_display = spend_usd/100000000; //total USD user display
console.log(spend_usd.toFixed(8)); //132320000000.00000000
console.log(spend_display.toFixed(8)); //1323.20000000
jsfiddle.net/XjLLS/
multiply the amount with 100000000 to get the no. of satoshis -
Proper Money Handling
multiply the amount with the rate
add 8 decimal places to the result
am i doing it right? i appreciate your help!
UPDATE:
i'm now use the bigdecimal.js library and made the following snippet:
var bigdecimal = require("bigdecimal");
var mode = bigdecimal.RoundingMode.HALF_EVEN(); //default: DOWN
var satoshi = new bigdecimal.BigDecimal("100000000");
var buy_amount = new bigdecimal.BigDecimal("132.32000000"); //amount in bicoin
var amount_minor = buy_amount.multiply(satoshi); //amount in satoshi
var sell_rate = new bigdecimal.BigDecimal("10.00000000"); //sell rate usd
var spend_minor = amount_minor.multiply(sell_rate);
var user_spend = spend_minor.divide(satoshi, 8, mode); //total usd user must spend
var user_display = user_spend.toString();
console.log(user_display);
jsfiddle.net/wwpWA/
the default rounding mode is DOWN but i set it to HALF_EVEN aka banker's rounding (banker’s rounding is common when working with money)
i hope all rounding errors are now gone! please correct me if i am wrong!

try this
var buy_amount = 132.32000000;
var buy_amount_satoshi = (parseFloat(buy_amount)*100000000).toFixed(8);
var sell_rate = 10.00000000;
var spend_satoshi = (parseFloat(buy_amount_satoshi)*parseFloat(sell_rate)).toFixed(8);
var spend_display = (parseFloat(spend_satoshi)/100000000).toFixed(8);

Related

I'm posting a tiny part of my code that is giving me an error. Only two lines need to be fixed to avoid "not a number' error

The following sections on my code are returning NaN error:
var nextTrain = frequency - restAferLastTrain;
var nextArrival = moment().add(nextTrain,
I was thinking that I may need to use moment.js to compute the calculations because they are dealing with time. If so, how can I fix them?
database.ref().on("child_added", function(childSnapshot, prevChildKey) {
console.log(childSnapshot.val());
//store in variables
var trainName = childSnapshot.val().train;
var destination =childSnapshot.val().trainOut;
var firstTime = childSnapshot.val().trainIn;
var frequency = childSnapshot.val().interval;
//makes first train time neater
var trainTime = moment.unix(firstTime).format("hh:mm");
//calculate difference between times
var difference = moment().diff(moment(trainTime),"minutes");
//time apart(remainder)
var restAferLastTrain = difference % frequency;
//minutes until arrival
var nextTrain = frequency - restAferLastTrain;
//next arrival time
var nextArrival = moment().add(nextTrain, "minutes").format('hh:mm');

Financial calculation with JavaScript (What´s wrong?)

I'm trying to make a financial calculation, but there's something wrong.
JS Code:
function count (){
var coda = 1.500;
var codb = 15;
var codc = 0.06;
var codx = 1;
var result = (codc/codx(codx-((codx+codc)*-codb)))*coda;
alert(result);
}
Message: undefined
In this line
var result = (codc/codx(codx-((codx+codc)*-codb)))*coda;
You try to execute the 2nd codx as a function (codx()). I guess you miss an operand there.
Try for example:
var result = (codc/codx / (codx-((codx+codc)*-codb)))*coda;
You are missing a * operator, so the compiler tries to call codx as a function.
To fix your computation, add the * operator as follow:
function count (){
var coda = 1.500;
var codb = 15;
var codc = 0.06;
var codx = 1;
var result = (codc/codx * (codx - ((codx+codc)*-codb)))*coda;
// ^
alert(result);
}
Missing * symbol? codx is being used as a fuction as a result.
var coda = 1.500;
var codb = 15;
var codc = 0.06;
var codx = 1;
var result = (codc/codx*(codx-((codx+codc)*-codb)))*coda;
alert(result);
Slightly off-topic but you should never use floating point arithmetic in financial calculations. Instead calculate by integer cents and then format for viewing as you like.
In this case,
It is better to split the mathematical calculation.
Example:
function count (){
var coda = 1.500;
var codb = 15;
var codc = 0.06;
var codx = 1;
var res1 = ((codx+codc)*-codb);
var res2 = codx-res1;
var result = (codc/codx*res2)*coda;
alert(result);
}
var count = function () {
var coda = 1.5; var codb = 15; var codc = 0.06; var codx = 1;
var result = (codc/codx ** here ** (codx-((codx+codc)* - codb))) * coda;
console.log(result);
}
P.S you have to put something after codx it's seen by javascript as an undefined function.
If this relates to paying down a loan at interest i per payment period, then you get that after n payments at a rate of r the reduced principal is
p*(1+i)^n-r*(1+i)^n-r*(1+i)^(n-1)-...-r*(1+i)
=
p*(1+i)^n - (1+i)*((1+i)^n-1)/i*r
If that is to be zero, loan repaid, then the necessary rate computes as
r = i/((1+i)*(1-(1+i)^(-n))) * p
which is in some aspects similar, in other fundamental aspects different from your formula.
var p = 1.500;
var n = 15;
var i = 0.06;
var x = 1+i;
var result = i/( x*( 1-Math.pow(x,-n) ) )*p;
alert(result);

jQuery function calculation wrong

I have this function
$("#exchange").on("change", function() {
var am = $(this).val();
var fee = $("#fee").val();
var cost = $("#cost").val();
var perc = fee / 100;
var tot = perc * am;
var fea = parseFloat(tot) + parseFloat(cost);
var total = parseFloat(am) - parseFloat(tot) - parseFloat(cost);
$("#return").val(total.toFixed(2));
$("#due").val("$" + fea.toFixed(2));
});
$("#return").on("change", function() {
var am = $(this).val();
var fee = $("#fee").val();
var cost = $("#cost").val();
var perc = fee / 100;
var tot = perc * am;
var fea = parseFloat(tot) + parseFloat(cost);
var total = parseFloat(am) + parseFloat(tot) + parseFloat(cost);
$("#exchange").val(total.toFixed(2));
$("#due").val("$" + fea.toFixed(2));
});
for example if #exchange = 16.85, #fee = 11, and #cost = 0
it should calculate #due = $1.85 and #return = 15.00
which is all correct. The problem is working in reverse I need it to calculate the same way but instead right now I get this
#return = 15, #fee = 11, and #cost = 0
it calculates #due = $1.65 and #exchange = 16.65
I understand why it is doing that, because it is calculating the fees from the var am which is the value of that field, which makes it very difficult for me to accomplish what I am trying to achieve which is to make it the same both ways, but obviously I cannot call var am to be the value of #exchange in my #return function because the field would be blank at that time which would calculate it at NAN so what can I do to make it to where all of my calculations are the same both ways, I have been trying for the better part of 5 hours to figure out what to do, but I am lost, a point in the right direction would be greatly appreciated.
This looks like a simple problem with your algebra to me. I see what you are trying to do. As it stands, you assume return = exchange - tot - cost and exchange = return + tot + cost. The problem is that you have assumed var tot is the same in your solution working forward and your solution working in reverse.
However, tot is equal to (fee/100) * exchange working forward and (fee/100) * return working backward, which breaks your assumptions for how to calculate exchange and return. My first step would be to move away from the var am assignment and naming, which seems to be confusing you, and call each exchange and return what they really are. This might help you form a correct algebraic solution, which you can then implement in JavaScript.
JSFiddle: https://jsfiddle.net/z6hrLbmc/
You are using wrong formula.
Use brutto=netto/(1-fee/100) instead of brutto=netto*(1+fee/100)
You have to distinguish whether the fee is applied to netto (+netto*fee/100) or to brutto (-brutto*fee/100).

Multiply a value based on a select box options

I have a small form with fixed costs based on where they are shipping from and going to with how many pallets.
For example UK Zone 1 to France Zone 1 = 20
Also UK Zone 3 to France Zone 4 = 68
var values = [
[20,25,35,40],
[36,42,50,56],
[42,56,52,68],
[60,70,68,72]
];
What i'm trying to achieve now is how would I multiply that total value.
So for example if the user selects UK Zone 1 going to France Zone 1 that is = £20 for 1 product
But if they select 2 from the select box the total cost should now be £40
Here is where I have got to but I cant get it to work
function updateValue() {
var fromCountry = document.querySelector('input[name="from_country"]:checked').value;
var toCountry = document.querySelector('input[name="to_country"]:checked').value;
var totalValues = values[fromCountry-1][toCountry-1];
var fixValues = document.querySelector('select[name="number"]');
var n = parseInt(fixValues.val(), 10);
if(fromCountry && toCountry) {
document.getElementById('cost').value = (totalValues * n);
}
}
Full Fiddle Here - http://jsfiddle.net/barrycorrigan/ZXHbq/3/
Help badly needed :-)
val() is jQuery function. Since you don't use jQuery, use fixValues.value. And don't forget to make a call updateValue(), which is missing in your fiddle.
This is the code I used to get it working:
function updateValue() {
var fromCountry = document.querySelector('input[name="from_country"]:checked').value;
var toCountry = document.querySelector('input[name="to_country"]:checked').value;
var totalValues = values[fromCountry-1][toCountry-1];
var fixValues = document.querySelector('select[name="number"]');
var n = parseInt(fixValues.value, 10);
if(fromCountry && toCountry) {
document.getElementById('cost').value = (totalValues * n);
}
}

How to add hours from 2 cells?

I have some google spreadsheet logbook where I store duration of some activities in hours format [[HH]:MM:SS]. The spreadsheet adds such cells with no issues. However when I try to add them via Google Script I get some garbage. What I found is that Date() object is implicitly created for such cells, but I cannot find API of that value type.
I know I can convert the data to "hour integers" by multiplying them by 24 but that is a nasty workaround as it demands duplication of many cells. I would rather like a solution that will allow to do that in google script itself.
here is a working function that does the trick.
I first tried to format it as a date but 36 hours is not really standard !! so I did a little bit of math :-) )
To get it working you should set a cell somewhere with value 00:00:00 that we will use as a reference date in spreadsheet standard. in my code it is cell D1(see comment in code, reference date in SS is in 1900 and in Javascript is in 1970 ... that's why it is a negative constant of 70 years in milliseconds...)
here is the code and below a screen capture of the test sheet + the logger
It would be a good idea to modify this code to make it a function that takes cell value as parameter and returns the result as an array for example ([h,m,s] or something similar), this code is only to show how it works.
function addHoursValues() {
var sh = SpreadsheetApp.getActive()
var hours1 = sh.getRange('A1').getValue();
var hours2 = sh.getRange('B1').getValue();
var ref = sh.getRange('D1').getValue().getTime();
//var ref = -2209161600000 // you could also use this but it would be less obvious what it really does ;-)
Logger.log(ref+' = ref');
var h1 = parseInt((hours1.getTime()/3600000)-ref/3600000);
var h2 = parseInt((hours2.getTime()/3600000)-ref/3600000);
Logger.log(h1+' + '+h2+' = '+(h1+h2))
var m1 = parseInt((hours1.getTime()-h1*3600000-ref)/60000);
var m2 = parseInt((hours2.getTime()-h2*3600000-ref)/60000);
Logger.log(m1+' + '+m2+' = '+(m1+m2))
var s1 = parseInt((hours1.getTime()-h1*3600000-m1*60000-ref)/1000);
var s2 = parseInt((hours2.getTime()-h2*3600000-m2*60000-ref)/1000);
Logger.log(s1+' + '+s2+' = '+(s1+s2))
var ts=s1+s2
var tm=m1+m2
var th=h1+h2
if(ts>59){ts=ts-60;tm++};
if(tm>59){tm=tm-60;th++}
Logger.log('sum = '+th+':'+tm+':'+ts)
}
EDIT : here are 2 "function" versions with corresponding test functions that show how to use it
function getHMS(hrs) {
var t = hrs.getTime()/1000;
var ref = -2209161600;
var h = parseInt((t-ref)/3600);
var m = parseInt((t-h*3600-ref)/60);
var s = parseInt(t-h*3600-m*60-ref);
return[h,m,s];// returns an array of 3 discrete values
}
function testHMS(){
var sh = SpreadsheetApp.getActive();
var hours1 = sh.getRange('A1').getValue();
var hours2 = sh.getRange('B1').getValue();
var sumS = getHMS(hours1)[2]+getHMS(hours2)[2];// add seconds
var sumM = getHMS(hours1)[1]+getHMS(hours2)[1];// add minutes
var sumH = getHMS(hours1)[0]+getHMS(hours2)[0];// add hours
if(sumS>59){sumS=sumS-60 ; sumM++}; // handles values >59
if(sumM>59){sumM=sumM-60 ; sumH++}; // handles values >59
Logger.log(sumH+':'+sumM+':'+sumS);
}
OR
function addHMS(hrs1,hrs2) {
var t1 = hrs1.getTime()/1000;
var t2 = hrs2.getTime()/1000;
var ref = -2209161600;
var h = parseInt((t1-ref)/3600)+parseInt((t2-ref)/3600);
var m = parseInt((t1-parseInt((t1-ref)/3600)*3600-ref)/60)+parseInt((t2-parseInt((t2-ref)/3600)*3600-ref)/60);
var s = parseInt(t1-parseInt((t1-ref)/3600)*3600-parseInt((t1-parseInt((t1-ref)/3600)*3600-ref)/60)*60-ref)
+parseInt(t2-parseInt((t2-ref)/3600)*3600-parseInt((t2-parseInt((t2-ref)/3600)*3600-ref)/60)*60-ref);
if(s>59){s=s-60 ; m++}; // handles values >59
if(m>59){m=m-60 ; h++}; // handles values >59
return[h,m,s];// returns sum in an array of 3 discrete values
}
function othertestHMS(){
var sh = SpreadsheetApp.getActive();
var hours1 = sh.getRange('A1').getValue();
var hours2 = sh.getRange('B1').getValue();
Logger.log(addHMS(hours1,hours2));
}

Categories