如何使用math.round()纠正不准确的Javascript数学
How to correct for inaccurate Javascript math with math.round()?
几天前我发布了这段代码,但讨论似乎对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>
通常,您希望最后舍入,因此在显示数据之前可以保持数学准确性。
以下是我将如何实现您的小库:
var SavingsLib = {
round : function(val, digits) {
var pow = Math.pow(10, digits);
return Math.round(pow * val) / pow;
},
padCurrency : function (val) {
var str = val.toString();
var parts = str.split(".");
return parts.length > 1 && parts[1].length == 1 ? str + "0" : str;
},
processForm : function() {
var daysPerMonth = parseInt(document.theForm4.elements[0].value);
var boardingsPerDay = parseInt(document.theForm4.elements[1].value);
var zone = document.getElementsByName("zonett")[0].value;
var savings = 0;
if(zone == "z4") savings = this.calculateSavings(daysPerMonth, boardingsPerDay, 4.25, 3.75);
else if(zone == "z3") savings = this.calculateSavings(daysPerMonth, boardingsPerDay, 3.75, 3.35);
else if(zone == "z2") savings = this.calculateSavings(daysPerMonth, boardingsPerDay, 3, 2.8);
else if(zone == "z1") savings = this.calculateSavings(daysPerMonth, boardingsPerDay, 2.5, 2.3);
else if(zone == "Base") savings = this.calculateSavings(daysPerMonth, boardingsPerDay, 1.5, 1.5);
this.showMessage(savings);
return false; // Don't submit form
},
calculateSavings : function(daysPerMonth, boardingsPerDay, price1, price2) {
var amount1 = (((daysPerMonth * boardingsPerDay) * price1) * 12);
var amount2 = (((daysPerMonth * boardingsPerDay) * price2) * 12);
return this.round(amount1 - amount2, 2);
},
showMessage : function(savings) {
alert("Your yearly savings if you buy Trip Tickets is $" + this.padCurrency(savings));
}
}
我的更改:
- 将函数封装到对象中以进行命名空间
- 将数学提取到单个方法中,以便您可以进行一次轮次调用
- 将消息的显示提取到一个方法中,以便您可以轻松修改它
- 添加了舍入到数字功能(因此
1.4500001
变为1.45
而不是1
) - 增加了一个垫货币函数(所以
1.4
变得1.40
)
你可以用 Math.round 写一个 kludge,但这会削减美分(不确定这是否适用于你的例子,它看起来可以)。你可能想要的是固定:
alert((102.000000004).toFixed(2)); // alerts "102.00"
这在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 )
编辑:打算把它放在评论中,但降价在那里不起作用?还在习惯所以...
无论如何,如果您愿意,您也可以将 Math.round 一起使用:
alert(Math.round(val * 100) / 100);
这可能仍然显示愚蠢的浮点问题,您可以使用另一个 .toFixed(现在您 100% 确定没有剩余的小数位,您没有正确舍入):
alert((Math.round(val * 100) / 100).toFixed(2));
编辑:要集成:
在脚本块的顶部添加以下内容:
function roundNicely(val) {
return (Math.round(val * 100) / 100).toFixed(2);
}
然后在警报中,将函数调用中的值包装prodBasett
:roundNicely(prodBasett)
(以及其他警报的类似值)
这有意义吗?
这很简单:
var prodZ4tt = Math.round(((one * two) * 4.25) *12) - (((one * two) * 3.75) *12);
虽然你可以理解为什么你可能会对语法感到困惑,因为JavaScript并不以其直观的做事方式而闻名;)。
注意:这会将数字四舍五入到最接近的整数,不会"向上舍入"。
对于需要精度的情况,您必须需要一个数学"任意精度库"...你可以在这里找到一篇好文章。
http://blog.thatscaptaintoyou.com/introducing-big-js-arbitrary-precision-math-for-javascript/
Javascript本身具有round,ceil和floor,可以将浮点数转换为整数。
var fl = 349.12783691847;
Math.round(fl) // 349
Math.ceil(f1) // 350
Math.floor(fl) // 349
当你做数学运算时,最好使用分布性,并正确使用括号。
Math.round(((((a + b) * (c - d)) % e) * f));
小心使用"NaN"(http://en.wikipedia.org/wiki/NaN)和非数字类型。
有好的一天
- 创建带有和不带有JavaScript的Bootstrap下拉菜单
- 任何浏览器都不支持javascript函数
- 无法't在不使用Javascript刷新页面的情况下多次将值传递给文本框
- 使用Javascript dosn'我不使用javascript
- Laravel 5.2动态下拉选择不填充(javascript)
- 如何在不退出javascript的情况下从javascript更新网页
- Sinon Spy不使用Javascript调用或应用程序
- 它是否创建了许多不利于JavaScript性能的变量
- 使用jquery(而不是javascript)在锚标记中附加html
- 方块几乎不动(Javascript)
- 在不使用javascript的情况下,可以在表单字段中设置文本占位符(以提示最终用户插入特定格式)
- 段落选择();我不使用javascript
- 找不到javascript元素
- 在 JavaScript 中对音频文件进行计时不准确
- 使用 javascript 库 draw2d 选择连接链接不准确
- Javascript减去数字是不准确的 - 为什么
- node.js下javascript中的日期函数不准确
- 为什么JavaScript'的数字*显示*大数是不准确的
- Javascript Math.cos和Math.sin不准确.有什么解决办法吗
- 如何使用math.round()纠正不准确的Javascript数学