如何使用 math.round() 纠正不准确的 Javascript 数学?
几天前我发布了这段代码,但讨论似乎对 Javascript 的弱点进行了哲学性的讨论(更不用说我自己作为“程序员”的明显弱点),然后就消失了,没有澄清解决方案。我希望有人能帮助纠正这个问题。
由于一种明显被称为“浮点数学”的现象,Javascript 在下面的计算器代码中返回算术上不准确的答案(.00000004 或正确答案下方的类似答案)。有人建议我通过“在变量上调用 math.round()”来四舍五入答案,我认为这对我的目的来说效果很好,只是我的 JS 功夫太弱了,因此在上下文中这样做的语法远远超出了我的预期。
在哪里/如何拨打此电话?到目前为止,我所有的尝试都失败了,即使我确信每一次尝试都不会失败。我肯定会很感激考虑到我对该主题的低水平知识的答案。对于外面的人来说,这一定是一个扣篮。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Untitled Document</title>
<script language="javascript">
<!-- Begin Trip Tickets Savings Calc script
function doMath4() {
var one = parseInt(document.theForm4.elements[0].value);
var two = parseInt(document.theForm4.elements[1].value);
var selection = document.getElementsByName("zonett")[0].value;
if(selection == "z4"){
var prodZ4tt = (((one * two) * 4.25) *12) - (((one * two) * 3.75) *12);
alert("Your yearly savings if you buy Trip Tickets is $" + prodZ4tt + ".");
}
else if(selection == "z3"){
var prodZ3tt = (((one * two) * 3.75) *12) - (((one * two) * 3.35) *12);
alert("Your yearly savings if you buy Trip Tickets is $" + prodZ3tt + ".");
}
else if(selection == "z2"){
var prodZ2tt = (((one * two) * 3) *12) - (((one * two) * 2.8) *12);
alert("Your yearly savings if you buy Trip Tickets is $" + prodZ2tt + ".");
}
else if(selection == "z1"){
var prodZ1tt = (((one * two) * 2.5) *12) - (((one * two) * 2.3) *12);
alert("Your yearly savings if you buy Trip Tickets is $" + prodZ1tt + ".");
}
else if(selection == "Base"){
var prodBasett = (((one * two) * 1.5) *12) - (((one * two) * 1.5) *12);
alert("Your yearly savings if you buy Trip Tickets is $" + prodBasett + ".");
}
}
// End Trip Tickets Savings Calc script -->
</script>
</head>
<body>
<form name="theForm4" class="calcform">
<h2>You Do the Math: Commuter Express Trip Tickets Vs. Cash</h2>
<div class="calcform-content">
<div class="formrow-calc">
<div class="calcform-col1">
<p>Days you commute on Commuter Express monthly:</p>
</div>
<div class="calcform-col2">
<input type="text">
</div>
<div class="calcform-col3"> </div>
</div>
<div class="clear"></div>
<div class="formrow-calc">
<div class="calcform-col1">
<p>Daily boardings on Commuter Express Bus:</p>
<table border="0" cellspacing="0" cellpadding="0" class="fareexampletable">
<tr>
<td colspan="2" class="savingsleft"><p class="ifyouride">EXAMPLE:</p></td>
</tr>
<tr>
<td class="savingsleft"><p><strong>Go to work:</strong></p></td>
<td class="savingsright"><p>1 time</p></td>
</tr>
<tr>
<td class="savingsleft"><p><strong>Come home from work:</strong></p></td>
<td class="additionline savingsright"><p>+1 time</p></td>
</tr>
<tr>
<td class="savingsleft"><p><strong>Total:</strong></p></td>
<td class="savingsright"><p>2 times</p></td>
</tr>
</table>
</div>
<div class="calcform-col2">
<input type="text">
</div>
<div class="calcform-col3"> </div>
</div>
<div class="clear"></div>
<div class="formrow-calc savings-zone">
<div class="calcform-col1">
<p>Choose Zone:</p>
</div>
<div class="calcform-col2">
<select name="zonett">
<option value="Base">Base</option>
<option value="z1">Zone 1</option>
<option value="z2">Zone 2</option>
<option value="z3">Zone 3</option>
<option value="z4">Zone 4</option>
</select>
</div>
</div>
<div class="formrow-calc">
<div class="calcform-col4-ce">
<button type="submit" onclick="doMath4()" class="btn-submit"><div class="btn-submit"><img src="img/btn_savings.png" alt="Show My Yearly Savings" /></div></button>
</div>
</div>
<div class="clear">
</div>
</div>
</form>
</body>
</html>
I posted this code a couple days back, but the discussion seemed to wax philosophical about the weaknesses of Javascript (not to mention my own obvious weaknesses as a "programmer") and then died out without ever clarifying a solution. I'm hoping someone will help rectify that.
Due to a phenomenon apparently known as "floating point math," Javascript returns an arithmetically inaccurate answer (.00000004 or similar below the correct answer) in the calculator code below. I was advised to round the answer up by "calling math.round() on the variable," which I think would work fine for my purposes, only my JS kung fu was too weak, and the syntax of doing so in context has thus far eluded me.
Where/how to I make this call? So far all my attempts have failed, even when I thought for sure each would not. I would sure appreciate an answer that takes into account my low-level knowledge of the subject. This has got to be a slam-dunk for somebody out there.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Untitled Document</title>
<script language="javascript">
<!-- Begin Trip Tickets Savings Calc script
function doMath4() {
var one = parseInt(document.theForm4.elements[0].value);
var two = parseInt(document.theForm4.elements[1].value);
var selection = document.getElementsByName("zonett")[0].value;
if(selection == "z4"){
var prodZ4tt = (((one * two) * 4.25) *12) - (((one * two) * 3.75) *12);
alert("Your yearly savings if you buy Trip Tickets is $" + prodZ4tt + ".");
}
else if(selection == "z3"){
var prodZ3tt = (((one * two) * 3.75) *12) - (((one * two) * 3.35) *12);
alert("Your yearly savings if you buy Trip Tickets is $" + prodZ3tt + ".");
}
else if(selection == "z2"){
var prodZ2tt = (((one * two) * 3) *12) - (((one * two) * 2.8) *12);
alert("Your yearly savings if you buy Trip Tickets is $" + prodZ2tt + ".");
}
else if(selection == "z1"){
var prodZ1tt = (((one * two) * 2.5) *12) - (((one * two) * 2.3) *12);
alert("Your yearly savings if you buy Trip Tickets is $" + prodZ1tt + ".");
}
else if(selection == "Base"){
var prodBasett = (((one * two) * 1.5) *12) - (((one * two) * 1.5) *12);
alert("Your yearly savings if you buy Trip Tickets is $" + prodBasett + ".");
}
}
// End Trip Tickets Savings Calc script -->
</script>
</head>
<body>
<form name="theForm4" class="calcform">
<h2>You Do the Math: Commuter Express Trip Tickets Vs. Cash</h2>
<div class="calcform-content">
<div class="formrow-calc">
<div class="calcform-col1">
<p>Days you commute on Commuter Express monthly:</p>
</div>
<div class="calcform-col2">
<input type="text">
</div>
<div class="calcform-col3"> </div>
</div>
<div class="clear"></div>
<div class="formrow-calc">
<div class="calcform-col1">
<p>Daily boardings on Commuter Express Bus:</p>
<table border="0" cellspacing="0" cellpadding="0" class="fareexampletable">
<tr>
<td colspan="2" class="savingsleft"><p class="ifyouride">EXAMPLE:</p></td>
</tr>
<tr>
<td class="savingsleft"><p><strong>Go to work:</strong></p></td>
<td class="savingsright"><p>1 time</p></td>
</tr>
<tr>
<td class="savingsleft"><p><strong>Come home from work:</strong></p></td>
<td class="additionline savingsright"><p>+1 time</p></td>
</tr>
<tr>
<td class="savingsleft"><p><strong>Total:</strong></p></td>
<td class="savingsright"><p>2 times</p></td>
</tr>
</table>
</div>
<div class="calcform-col2">
<input type="text">
</div>
<div class="calcform-col3"> </div>
</div>
<div class="clear"></div>
<div class="formrow-calc savings-zone">
<div class="calcform-col1">
<p>Choose Zone:</p>
</div>
<div class="calcform-col2">
<select name="zonett">
<option value="Base">Base</option>
<option value="z1">Zone 1</option>
<option value="z2">Zone 2</option>
<option value="z3">Zone 3</option>
<option value="z4">Zone 4</option>
</select>
</div>
</div>
<div class="formrow-calc">
<div class="calcform-col4-ce">
<button type="submit" onclick="doMath4()" class="btn-submit"><div class="btn-submit"><img src="img/btn_savings.png" alt="Show My Yearly Savings" /></div></button>
</div>
</div>
<div class="clear">
</div>
</div>
</form>
</body>
</html>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
一般来说,您希望最后舍入,因此您可以保持数学准确性,直到显示数据为止。
以下是我将如何实现您的小库:
我的更改:
1.4500001
变为1.45
而不是1
)1.4
变为1.40
)In general you want to round last, so you maintain mathematical accuracy up until the point that data is displayed.
Here is how I would implement your little library:
My changes:
1.4500001
becomes1.45
instead of1
)1.4
becomes1.40
)您可以使用 Math.round 编写一个拼凑,但这会造成损失(不确定这是否适用于您的示例,看起来似乎可以)。您可能想要的是修复:
这在 IE 中不会四舍五入,但据我所知,这对您的情况并不重要。
(文档:https://developer.mozilla.org/en/JavaScript/ Reference/Global_Objects/Number/toFixed , http://www.codingforums.com /showthread.php?t=102421 、 http://msdn. microsoft.com/en-us/library/sstyff0z.aspx )
编辑:打算将其放在评论中,但 Markdown 在那里不起作用?仍然习惯这样......
无论如何,如果您愿意,您也可以使用 Math.round 的拼凑:
这可能仍然显示愚蠢的浮动问题,为此您可以使用另一个 .toFixed (现在您 100% 确定)没有剩余的小数位,您没有正确舍入):
编辑:集成:
将其添加到脚本块的顶部:
然后在警报中,将值
prodBasett
包装在函数调用中:< code>roundNicely(prodBasett) (其他警报也类似)这有意义吗?
You can write a kludge with Math.round, but that will nuke cents (not sure if this applies in your example, it sort of looks like it could). What you may want is toFixed:
This does NOT round in IE, but from what I can tell this will not matter in your case.
(docs: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Number/toFixed , http://www.codingforums.com/showthread.php?t=102421 , http://msdn.microsoft.com/en-us/library/sstyff0z.aspx )
Edit: intended to put this in the comments, but markdown doesn't work there? Still getting used to SO...
Anyhow, you can also use a kludge with Math.round if you prefer:
Which may still display the silly float issues, for which you could use another .toFixed (and now you're 100% sure there's no leftover decimal places you're not rounding properly):
Edit: to integrate:
Add this at the top of your script block:
Then in your alerts, wrap the value
prodBasett
in the function call:roundNicely(prodBasett)
(and similar for the other alerts)Does that make sense?
它非常简单:
尽管您可能对语法感到困惑是可以理解的,因为 JavaScript 不是以其直观的做事方式而闻名。 ;)
注意: 这会将数字四舍五入到最接近的整数,而不是“向上舍入”。
It's very simple:
Although it's understandable why you might get confused about syntax, since JavaScript is not known for its intuitive way of doing things. ;)
Note: This rounds the number to the nearest integer, it doesn't "round up."
对于需要精度的情况,您必须需要一个数学“任意精度库”......您可以在这里找到一篇好文章。
http://blog.thatscaptaintoyou.com/introducing- big-js-任意-精度-math-for-javascript/
JavaScript 本身具有 round、ceil 和 Floor 来将浮点数转换为整数。
当您进行数学运算时,使用分配律和正确使用括号是很好的做法。
请小心“NaN”(http://en.wikipedia.org/wiki/NaN) 和非数字类型。
祝你今天过得愉快
For that cases when you need precision, you must need an Math "Arbitrary Precision Library"... you could find a good article here.
http://blog.thatscaptaintoyou.com/introducing-big-js-arbitrary-precision-math-for-javascript/
Javascript natively have round, ceil and floor to convert floats to integers.
when you do math operations, is good practice use distributivity, and properly use of parenthesis.
Be careful with "NaN" (http://en.wikipedia.org/wiki/NaN) and non Number types.
have a nice day