Easy- Function arguments - javascript

I'm currently struggling with getting the below calcRatio function calculate properly. This is probably basic maths!
The below function works as expected:
function calcRatio(){
var r = frontRing.value/backCog.value;
return r;
}
e.g. frontRing = 52, backCog = 11 r=4.7272....
The below gives me the wrong result:
function calcRatio(){
var r = frontRing.value/(backCog.value + 5);
return r;
}
e.g. frontRing = 52, backCog = 11 r=0.4521.
I ultimately want the 5 to be swapped with an argument.
I am also unable to set the frontRing and backCog variable as .value's without doing it within the function. Could this be causing the issue?
Codepen link

When you expect the extracted value to be a string and have additional computations, it is preferred you use either
parseInt( value , 10) - for integers
parseFloat( value ) - for decimals
In the use case var r = frontRing.value/(backCog.value + 5);
backCog.value is a string since it it a value of input element. When you use + to add a number, it performs a concatenation instead of addition.
var backCogValue = backCog.value; // "11";
"11" + 5 --> 115 and not 16 as you expected.
So the right way to write this piece of code is to use either of the above methods before you want to add a number.
var frontRingValue = parseFloat(frontRing.value);
var backCogValue = parseFloat(backCog.value);
var r = (frontRingValue/ (backCogValue + 5)).toFixed(4);
toFixed is use to format into the number of decimal points that you are expecting.
If 5 is the argument that is passed to the function, then your code will look like
function calcRatio(param) {
var frontRingValue = parseFloat(frontRing.value);
var backCogValue = parseFloat(backCog.value);
var paramValue = parseFloat(paramValue);
var r = (frontRingValue/ (backCogValue + paramValue)).toFixed(4);
}

Related

in Javascript, exist a function that return only the fractional part of a number, like Math dot something.... ? How can I get it? [duplicate]

I have a floating point number:
var f = 0.1457;
Or:
var f = 4.7005
How do I get just the fraction remainder as integer?
I.e. in the first example I want to get:
var remainder = 1457;
In the second example:
var remainder = 7005;
function frac(f) {
return f % 1;
}
While this is not what most people will want, but TS asked for fract as integer, here it is:
function fract(n){ return Number(String(n).split('.')[1] || 0); }
fract(1.23) // = 23
fract(123) // = 0
fract(0.0008) // = 8
This will do it (up to the 4 digits that you want, change the multipler (10000) to larger or smaller if you want smaller or larger number):
Math.ceil(((f < 1.0) ? f : (f % Math.floor(f))) * 10000)
parseInt(parseFloat(amount).toString().split('.')[1], 10)
You can subtract the floor of the number, giving you just the fractional part, and then multiply by 10000, i.e.:
var remainder = (f-Math.floor(f))*10000;
I would argue that, assuming we want to display these values to the user, treating these numbers as strings would be the best approach. This gets round the issue of fractional values such as 0.002.
I came accross this issue when trying to display prices with the cents in superscript.
let price = 23.43; // 23.43
let strPrice = price.toFixed(2) + ''; // "23.43"
let integer = strPrice.split(".")[0] // "23"
let fractional = strPrice.split(".")[1] // "43"
This also depends on what you want to do with the remainder (as commenters already asked). For instance, if the base number is 1.03, do you want the returned remainder as 3 or 03 -- I mean, do you want it as a number or as a string (for purposes of displaying it to the user). One example would be article price display, where you don't want to conver 03 to 3 (for instance $1.03) where you want to superscript 03.
Next, the problem is with float precision. Consider this:
var price = 1.03;
var frac = (price - Math.floor(price))*100;
// frac = 3.0000000000000027
So you can "solve" this by slicing the string representation without multiplication (and optional zero-padding) in such cases. At the same time, you avoid floating precision issue. Also demonstrated in this jsfiddle.
This post about floating precision might help as well as this one.
var strNumber = f.toString();
var remainder = strNumber.substr(strNumber.indexOf('.') + 1, 4);
remainder = Number(reminder);
Similar method to Martina's answer with a basic modulo operation but solves some of the issues in the comments by returning the same number of decimal places as passed in.
Modifies a method from an answer to a different question on SO which handles the scientific notation for small floats.
Additionally allows the fractional part to be returned as an integer (ie OP's request).
function sfract(n, toInt) {
toInt = false || toInt;
let dec = n.toString().split('e-');
let places = dec.length > 1
? parseInt(dec[1], 10)
: Math.floor(n) !== n ? dec[0].split('.')[1].length : 0;
let fract = parseFloat((n%1).toFixed(places));
return toInt ? fract * Math.pow(10,places) : fract;
};
Tests
function sfract(n, toInt) {
toInt = false || toInt;
let dec = n.toString().split('e-');
let places = dec.length > 1
? parseInt(dec[1], 10)
: Math.floor(n) !== n ? dec[0].split('.')[1].length : 0;
let fract = parseFloat((n%1).toFixed(places));
return toInt ? fract * Math.pow(10,places) : fract;
};
console.log(sfract(0.0000005)); // 5e-7
console.log(sfract(0.0000005, true)); // 5
console.log(sfract(4444)); // 0
console.log(sfract(4444, true)); // 0
console.log(sfract(44444.0000005)); // 5e-7
console.log(sfract(44444.00052121, true)); // 52121
console.log(sfract(34.5697)); // 0.5697
console.log(sfract(730.4583333333321, true)); // 4583333333321
#Udara Seneviratne
const findFraction = (num) => {
return parseInt( // 5.---------------- And finally we parses a "string" type and returns an integer
// 1. We convert our parameter "num" to the "string" type (to work as with an array in the next step)
// result: "1.012312"
num.toString()
// 2. Here we separating the string as an array using the separator: " . "
// result: ["1", "012312"]
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split
.split('.')
// 3. With help a method "Array.splice" we cut the first element of our array
// result: ["012312"]
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
.splice(1.1)
// 4. With help a method "Array.shift" we remove the first element from an array and returns that
// result: 012312 (But it's still the "string" type)
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift
.shift()
)
}
// Try it
console.log("Result is = " + findFraction (1.012312))
// Type of result
console.log("Type of result = " + typeof findFraction (1.012312))
// Some later operation
console.log("Result + some number is = " + findFraction (1.012312) + 555)

Convert currency compact notation (e.g. '$1.5k') into integer (e.g. 1500)

I have a column with different currencies and ways to write numbers that I want to convert to numbers, ex:
$1.5M
€1.5B
$1.5B
$1.5k
€1.5k
$1.5K
All the .tests I run on my regex return false. I think the issue is that the value returned has square brackets but I don't know how to take only the number.
When I put a log, it shows: Info [1.5] and not Info 1.5
function ConvertToInteger (Sheet,columnToConvert) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName(Sheet);
var shLastRow = sh.getLastRow();
var shdata = sh.getDataRange().getValues();
var regExp = new RegExp('[.,0123456789]+');
var regExpBillionDollar = new RegExp('[\$][.,0-9]+[B$]','g');
var regExpMillionDollar = new RegExp('[\$][.,0-9]+[M$]','g');
var regExpKiloDollar = new RegExp('[\$][.,0-9]+[K$]','g');
var regExpBillionEuros = new RegExp('[\‎€][.,0-9]+[B$]','g');
var regExpMillionEuros = new RegExp('[\‎€][.,0-9]+[M$]','g');
var regExpKiloEuros = new RegExp('[\‎€][.,0-9]+[K$]','g');
for (var i = 1; i < shLastRow; i++) {
var DataConverted = regExp.exec(shdata[i][columnToConvert])
if (regExpBillionDollar.test(DataConverted)) {
sh.getRange(i+1, columnToConvert+1).setValue((DataConverted *1000) * 0.9); //Convert to Euros
}
}
}
If you need to do both (convert to integer and get exchange rate product) within one function, you can make use of String.prototype.replace() which accepts callback function as its second argument. You may have this function to process matching groups (([\$\€]) - currency, either dollar or euro; (\d+.\d+) - floating point number, i.e. 1.5; ([K,M,B]) - respective suffix) in a way that
suffix is turned into multiplier (10 in power of 3, 6, 9, which corresponds to value of respective object key {'K': 10**3, 'M': 10**6, 'B': 10**9}
currency character is turned either into 1 (for dollar) or 1.16 (exchange rate for euro)
To cast resulting string into number, you may simply prepend +, to drop decimal part (equivalent to Math.floor()), you may use 0|:
const src = ['$1.5M','€1.5B','$1.5B','$1.5k','€1.5k','$1.5K', '$800'],
exRateToDollar = {'$': 1, '€': 1.16},
translate = (s, exchangeRate) =>
0|+s
.toUpperCase()
.replace(
/^([\$\€])(\d+(\.\d+)?)([K,M,B])?$/,
(_, currency, n, __, suffix) =>
exchangeRate[currency]*
n*
(suffix ? {'K':10**3, 'M':10**6, 'B':10**9}[suffix] : 1))
console.log(src.map(s => translate(s, exRateToDollar)))
.as-console-wrapper{min-height:100%;}

returning NaN and Undefined in JavaScript

var currDice, totDice, dice, complete;
function moveIt(){
dice = Math.floor(Math.random()*6) + 1,
currDice = 40,
totDice = totDice+complete,
complete = dice * currDice
return totDice;
};
The function moveIt returns NaN.
It should return multiple of 40 till six randomly and keep the previous value.
If I remove it returns Undefined.
I know it is a scope problem. Please help.
You are using complete before initialising it! you habe to swap your lines of code:
function moveIt(beforeTotal) {
var dice = Math.floor(Math.random()*6) + 1;
var currDice = 40;
var complete = dice * currDice;
var totDice = (beforeTotal || 0)+complete;
return totDice;
};
var total = moveIt();
console.log(total);
total = moveIt(total);
console.log(total);
I try to point out how this method work.
You can call this function without an inital value. Then (beforeTotal || 0) is (undefined || 0) and will evaluate to 0, that's JS logic, and you get the result for one dice.
If you pass a value to this function it will be used to add complete to it. By passing 1000 and complete gets 120, you get 1120 out of it.
All other variables are only available in this function.
Initialy totDIce is undefined and when you add undefined to something, you get the value casted to NaN
function moveIt(){
//memoizing the mutable value as key of the function itself
moveIt.totDice = moveIt.totDice || 0;
// you might wanna wrap it with parseInt()/Math.floor()/Math.ceil()
var dice = Math.floor(Math.random()*6) + 1;
var currDice = 40;
var complete = dice * currDice;
var totDice = totDice+complete;
return moveIt.totDice ;
};
var totDice; will have undefined and that's why you get NaN
Assign totDice = 0 on the first line...
Also move complete = dice * currDice line above because complete has no value yet
var currDice, totDice = 0, dice, complete;
function moveIt(){
dice = Math.floor(Math.random()*6) + 1,
currDice = 40,
complete = dice * currDice,
totDice = totDice+complete
return totDice;
};
you can use the browser's integrated console.
In Chrome: Tools > Javascript Console. Or CTRL + SHIFT + J. There you can console.log from your code and watch it there, or you can use the Sources tab (at the top of the panel). Navigate to the file, click on it and you can put a breakpoint in the line you want by ckicking the line number.
In Firefox: Tools > development > Web console. Or CTRL + SHIFT + K. Yu can debug in a similar fashion like the aforementioned.
You can also use tools like Firebug. See https://getfirebug.com/wiki/index.php/Script_Debugging

Create a float from two int numbers in JavaScript

How can I construct a float value from two whole values?
var amountBeforeComma = 5;
var amountAfterComma = 234;
var amount = ?? //amount == 5.234
There's the math way, using logarithms:
var amountBeforeComma = 5;
var amountAfterComma = 234;
var amount = amountBeforeComma +
amountAfterComma * Math.pow(10, -(Math.floor(Math.log10(amountAfterComma)) + 1));
console.log(amount);
Math.log10(amountAfterComma) gives us the common logarithm of amountAfterComma, then Math.floor(...) on that gives us the characteristic of it (2 in your example), which is (as the linked Wikipedia page puts it) "how many places the decimal point must be moved so that it is just to the right of the first significant digit". Then we add one to that and make it a negative (e.g., -3 in your example) and raise raise 10 to that power to get a value to multiply it by (0.001 in your example) to put it where it should go. Add the amountBeforeComma and we're done.
Or the string then parse way:
var amountBeforeComma = 5;
var amountAfterComma = 234;
var amount = parseFloat(amountBeforeComma + "." + amountAfterComma);
console.log(amount);
(Or use +(amountBeforeComma + "." + amountAfterComma) to convert with implicit coercion rather than explicit parsing.)
Since no one mentioned... There's the JavaScript way:
var num = +(amountBeforeComma + "." + amountAfterComma);
You can make it by casting numbers to strings and then parsing it as float.
var amount = parseFloat(amountBeforeComma + '.' + amountAfterComma);

How to sum 2 numbers witout rounding

I have 2 numbers
a = 1548764548675465486;
b = 4535154875433545787;
when I sum these number they are rounded to
a => 1548764548675465500
b => 4535154875433545700
and a + b returns 6083919424109011000 while it should return 6083919424109011273
is there a javascript solution to solve this problem witout the use of a library ?
To work around the precision limitations associated with JavaScript's numbers, you will need to use a BigInteger library like the popular one offered here: http://silentmatt.com/biginteger/
Usage:
var a = BigInteger("1548764548675465486");
var b = BigInteger("4535154875433545787");
var c = a.add(b);
alert(a.toString() + ' + ' + b.toString() + ' = ' + c.toString());
// Alerts "1548764548675465486 + 4535154875433545787 = 6083919424109011273"
Demo: http://jsfiddle.net/69AEg/1/
There are no integers in Javascript, all numbers are double precision floating point.
That gives you a precision of around 15-16 digits, which is what you are seeing.
as per this question
and potential solution i.e. use a library
Personally, I would not use javascript, never been great at numbers. Just try typing 0.1 + 0.2 into any browsers console window. Result is 0.30000000000000004.
Send the calculation to your server side language (as a string) and do the work there, you should have a better outcome.
Technical article on the nuances of floating point numbers here, if you interested
Well, here is a solution I found witout the use of any external library, all I need to do is to define a class that had a property value wich should be a string, and define the function plus
function LongNumber()
{
// it takes the argument and remove first zeros
this.value = arguments[0].toString();
while(this.value[0]==="0")
this.value = this.value.substr(1);
// this function adds the numbers as string to another string and returns result as LongNumber
this.plus = function (Num)
{
var num1 = pad(Num.value.length, this.value);
var num2 = pad(this.value.length, Num.value);
var numIndex = num1.length;
var rest = 0;
var resultString = "";
while (numIndex)
{
var number1 = parseInt(num1[(numIndex)-1]);
var number2 = parseInt(num2[(numIndex--)-1]);
var addition = (number1+number2+rest)%10;
rest = parseInt((number1+number2+rest)/10);
resultString = addition.toString() + resultString;
}
return new LongNumber((rest?rest.toString():"") + resultString);
}
function pad(width, string)
{
return (width <= string.length) ? string : pad(width, '0' + string)
}
}
All i need to do now is to declare 2 LongNombers and use the function plus
var Number1 = new LongNumber("1548764548675465486");
var Number2 = new LongNumber("4535154875433545787");
var Result = Number1.plus(Number2);
Result.value // returns "6083919424109011273"

Categories