I'm building an app that displays the weather and converts the current temp from Fahrenheit to Celsius. For some reason, when the conversion takes place, the math isn't coming out right. Oddly, after clicking the button 5 - 6 times, it starts working correctly.
My best guess is that I'm doing something wrong with parseInt() or maybe a variable isn't being updated.
Thoughts?
function toggleUnits(){
if(wUnit.innerHTML == "C"){
var oldTemp = parseInt(wTemp.innerHTML, 10),
newTemp = oldTemp * 9 / 5 + 32;
wTemp.innerHTML= newTemp;
wUnit.innerHTML = "F";
unitToggle.innerHTML ="Switch to Celsius";
}else{
var oldTemp = parseInt(wTemp.innerHTML, 10),
newTemp = (oldTemp-32) * 5 / 9;
wTemp.innerHTML= newTemp;
wUnit.innerHTML = "C";
unitToggle.innerHTML ="Switch to Fahrenheit";
}
}
CodePen: https://codepen.io/abenjamin/pen/ZojJLq
It is helpful to scale up your decimal values by a consistent multiplier and represent all numbers as integers. For example, use 806 degrees instead of 80.6 degrees (multiply by 10) for your temperature calculations. This is to avoid the nuances with floating-point math. In JavaScript we only have the floating-point data type for numeric values, but luckily integer math under the floating-point data-type is exact. Therefore scaling up decimal values to integers (e.g., 2550 degrees instead of 25.50 degrees ) resolves the issue.
For example (converting from fahrenheit to celsius):
console.log((80.6-32) * 5 / 9); // outputs 26.999999999999996
Corrected with:
console.log((806-320) * 5 / 9 / 10 ); // outputs 27
The reason your calculator works correctly sometimes but not other times is because the temperature API sometimes returns integers, but other times returns decimal values.
I wouldn't recommend using parseInt to resolve this issue because it will round decimal values and you'll lose precision.
Related
Is there a reason why some Javascript programmers use the following syntax to remove decimals?
Math.ceil(averageCost / 10) * 10;
Why wouldn't we just use Math.ceil? Doesn't it effectively do the same thing as the above? Is there a condition where Math.ceil doesn't work?
Initially I thought maybe this would eliminate string cases and return a zero, but in the following code, the results are NaN -
var name = "Gary";
console.log(Math.ceil(name / 10)); // NaN
console.log(Math.ceil(name)); // NaN
So I'm at a loss for why I'd see a division by 10 with a subsequent multiplication of 10.
The construct:
Math.ceil(averageCost / 10) * 10;
Does a form of rounding. It has the net effect of rounding up to the nearest whole number multiple of 10. So:
11 => 20
20 => 20
21 => 30
11.99 => 20
Math.ceil(averageCost / 10) divides by 10 and rounds up to the nearest whole number (removing all decimal portions and all ones) and then the * 10 brings it back to the same numeric range it was originally in, but without the parts removed by the rounding.
Here's an example showing a number of results:
const nums = [10,11,15,18,19,20,21,10.1,11.99,20.19];
for (let num of nums) {
let result = Math.ceil(num/10) * 10;
console.log("Input: ", num, ", Output: ", result);
}
Why wouldn't we just use Math.ceil? Doesn't it effectively do the same thing as the above? Is there a condition where Math.ceil doesn't work?
This combination rounds up to the nearest whole number multiple of 10 whereas Math.ceil() only rounds up to the nearest whole number. So, the two cases you ask about have different uses. Use the one that accomplishes what you want to accomplish. For a number where the integer portion is already a power of ten such as 10.3, the two would have the same output, but for any other number such as 11.3, the two would not have the same output.
Math.ceil(11.3) === 11
(Math.ceil(11.3 / 10) * 10) === 20
Is there a condition where the Math.ceil() function in Javascript doesn't remove decimals from the output?
No. There is not. It's whole function is to round up to the nearest whole number (thus removing any decimal fraction from the number).
So I'm at a loss for why I'd see a division by 10 with a subsequent multiplication of 10.
To round up to the nearest whole number multiple of 10.
temperatureReading = Math.round(temperatureReading * 10) / 10
gives me 26.29999999999999999999 instead of 26.3
And 26.00000000001 instead of 26.0
I get alternating 2 values from the temperature sensor: 26.33 and 26.3200000
After the conversion I have: 26.2999999999999
The number of the repeating digits above is just an example. My display on the micro bit is not wide enough to see them all.
I use toString() to display the values.
Unfortunately, toFixed() and toPrecision() is not available on the micro:bit
Can the rounding be achieved by some other operations?
With the following code I can now get numbers with 1 decimal as a string:
let temperatureStr = Math.round(temperatureReading * 10).toString()
let temperature = temperatureStr.slice(0, temperatureStr.length - 1) + "." + temperatureStr.slice(temperatureStr.length - 1);
I first multiply the number by 10 and convert the result to a string. Then, I insert the decimal point before the last digit. This gives me the string I want to print.
Here is the Example:
For example, suppose we have a float 13.4. In binary, it can be written as: 1101.01100110011001100110011001100110011兮.
Suppose the system stores bits up to 10 decimal places. So 13.4 is stored as: 1101.0110011001 (only 10 decimal places now)
Because of this change, if you convert 1101.0110011001 back to base 10, you get 13.399414. In essence 13.399414 is stored rather than 13.4 in this case!
So given a floating point in base 10, an integer n which represents the number of decimal places as defined above, output the stored value of the float to three decimal places.
So How can i convert using javascript:- input 13.4 and output 13.399
Going off of the comment by #Jaromanda X
function cut(num, base, len) {
base = Math.pow(2, base);
return (parseInt((num * base).toString(2), 2) / base).toFixed(len);
}
You can get a number with a desired number of fractional digits by shifting it to the left by that number of places, dropping the remaining digits on the right by flooring it, and shifting it back right. This works in any base - base 2 in your case:
Math.floor(13.4 * 2**10) / 2**10
Math.floor(13.4 * Math.pow(2, 10)) / Math.pow(2, 10)
Math.floor(13.4 * (1<<10)) / (1<<10)
You can use the Basenumber.js library. Just create an instance in decimal, an parse it to binary:
// Set precision decimals you want
Base.setDecimals(100);
// create instance in decimal
let x = Base(13.4);
// Transform x to binary
let y = x.toBin();
console.log(x.valueOf());
console.log(y.valueOf());
// Transform y to decimal again
let z = y.toDec();
// Since 13.4 has no exact binary representation it would not be accurate
console.log(z.valueOf());
// But you can round the value so get again 13.4
let rounded = z.round(10); // round 10 decimals
console.log(rounded.valueOf());
<script src='https://cdn.jsdelivr.net/gh/AlexSp3/Basenumber.js#main/BaseNumber.min.js'></script>
I am working on a calculator to figure out how much of a substance is still in someones system after x amount of days. The three variables are the amount taken daily, the number of days it has been taken, and the half-life of the substance. My formula below may not be 100% correct, but that's not the problem I'm having at this time.
I'm having problems with the answer being converted to an integer. Where am I going wrong? I need everything to stay with a float (decimal) value.
P.S. Ignore comments, they were just added on here to explain variables.
dose = 8.00 // 8mg dose
meta = 70.0 // 70 hour half-life
days = 5 // 5 days of use
sys = dose * (1.0/2.0) ^ (24.0/meta)
for(x=2; x <= days; x++){
sys = ((sys+dose) * (1.0/2.0) ^ (24.0/meta))
}
Thanks in advance!
^ in javascript isn't the mathematical 'raise to a power' operator, it is the bitwise XOR operator, and will always give a integer. You want to use pow from the Math class.
Try
sys = dose*Math.pow((1.0/2.0), (24.0/meta))
and
sys = (sys+dose)*Math.pow((1.0/2.0), (24.0/meta))
instead
Yeah, JavaScript automatically casts whole numbers to integers. Once it has a decimal value (other than 0), e.g. 1.5, it should respect the float.
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 9 years ago.
I'm trying to create a simple percentage calculator using javascript.
I try a simple calculation in the console (try it):
106 / 100 * 10
And it returns me:
10.600000000000001
What is going on here? Brackets makes no difference and this doesn't occur for every number. I would expect the result to be 10.6 right? Can anyone offer an explanation? This is not browser specific, it happens in Chrome dev tools and firebug.
No, the result is correct enough (even if changing the order of operations could lead to a different result), that's one of the miracles of IEEE754 floating point storage : a consequences of the fact that numbers aren't stored like you see them, that is some decimal digits and a comma but as
K * 2 ^ N
where K and N are signed integers.
As of course not all numbers can be stored exactly, others are only approached.
I'd suggest you to read this introduction to IEEE754 computing.
What you need is to format the number when outputting it to the user, for example with
var string = myNumber.toFixed(1);
Not all decimal numbers have exact representations in binary, so problems like this happen pretty regularly when you try to do math with floats.
Converted to binary, your operation is as follows:
106 = 64 + 32 + 8 + 2 = 1101010
100 = 64 + 32 + 4 = 1100100
1101010 / 1100100 = 1010.10011001100...
You then multiply this by 10, or 101 in binary and get
1010.10011001100... * 101 = 1010.1001100110011001100...
Which does not quite evaluate to 10.6.
In your particular case, the number has been truncated at 1010.10011001100110011001100110011001, or 36 bits.
Try Below :
Var myAnswer = 106 / 100 * 10;
var result = myAnswer.toFixed(1);
Javascript: formatting a rounded number to N decimals
How this will work for you...
Enajoy your day..!!!
Double precision. Numbers are stored in the computer as powers of two, e.g. 1/2 + 1/4 + 1/8... so when printed as decimals they may not be exact.
you could try (106 / 1000) * 100