2011-09-08 55 views
1

我需要javascript帮助。我正在使用一个简单的js文件为一个小的在线商店。演示页面的网址为:http://www.k-prim.biz/Esther/Store/proba.html 我使用的JavaScript称为orderform04.js。有一个错误:当为product1输入q-ty 3时 - 价格为4.8,结果是14.399999999999999而不是14.4!需要帮助来使用Javascript

任何人都可以帮助解决这个问题吗?

的JavaScript也在这里:

function OrderForm(prefix, precision, firstChoice) { 

this.prefix = prefix ? prefix : ''; 

// **************************** 
// Configure here 
// **************************** 
// names - Set these according to how the html ids are set 
this.FORM_NAME = this.prefix + 'frmOrder'; 
this.BTN_TOTAL = this.prefix + 'btnTotal'; 
this.TXT_OUT = this.prefix + 'txtTotal'; 

// partial names - Set these according to how the html ids are set 
this.CHK = this.prefix + 'chk'; 
this.SEL = this.prefix + 'sel'; 
this.PRICE = this.prefix + 'txtPrice'; 

// precision for the decimal places 
// If not set, then no decimal adjustment is made 
this.precision = precision ? precision : -1; 

// if the drop down has the first choice after index 1 
// this is used when checking or unchecking a checkbox 
this.firstChoice = firstChoice ? firstChoice : 1; 
// **************************** 

// form 
this.frm = document.getElementById(this.FORM_NAME); 

// checkboxes 
this.chkReg = new RegExp(this.CHK + '([0-9]+)'); 
this.getCheck = function(chkId) { 
    return document.getElementById(this.CHK + chkId); 
}; 

// selects 
this.selReg = new RegExp(this.SEL + '([0-9]+)'); 
this.getSelect = function(selId) { 
    return document.getElementById(this.SEL + selId); 
}; 

// price spans 
this.priceReg = new RegExp(this.PRICE + '([0-9]+)'); 

// text output 
this.txtOut = document.getElementById(this.TXT_OUT); 

// button 
this.btnTotal = document.getElementById(this.BTN_TOTAL); 

// price array 
this.prices = new Array(); 

var o = this; 
this.getCheckEvent = function() { 
    return function() { 
     o.checkRetotal(o, this); 
    }; 
}; 

this.getSelectEvent = function() { 
    return function() { 
     o.totalCost(o); 
    }; 
}; 

this.getBtnEvent = function() { 
    return function() { 
     o.totalCost(o); 
    }; 
}; 

/* 
* Calculate the cost 
* 
* Required: 
* Span tags around the prices with IDs formatted 
* so each item's numbers correspond its select elements and input checkboxes. 
*/ 
this.totalCost = function(orderObj) { 
    var spanObj = orderObj.frm.getElementsByTagName('span'); 
    var total = 0.0; 
    for (var i=0; i<spanObj.length; i++) { 
     var regResult = orderObj.priceReg.exec(spanObj[i].id); 
     if (regResult) { 
      var itemNum = regResult[1]; 
      var chkObj = orderObj.getCheck(itemNum); 
      var selObj = orderObj.getSelect(itemNum); 
      var price = orderObj.prices[itemNum]; 
      var quantity = 0; 
      if (selObj) { 
       quantity = parseFloat(selObj.options[selObj.selectedIndex].text); 
       quantity = isNaN(quantity) ? 0 : quantity; 
       if (chkObj) chkObj.checked = quantity; 
      } else if (chkObj) { 
       quantity = chkObj.checked ? 1 : 0; 
      } 
      total += quantity * price; 
     } 
    } 
    if (this.precision == -1) { 
     orderObj.txtOut.value = total 
    } else { 
     orderObj.txtOut.value = total.toFixed(this.precision); 
    } 
}; 

/* 
* Handle clicks on the checkboxes 
* 
* Required: 
* The corresponding select elements and input checkboxes need to be numbered the same 
* 
*/ 
this.checkRetotal = function(orderObj, obj) { 
    var regResult = orderObj.chkReg.exec(obj.id); 
    if (regResult) { 
     var optObj = orderObj.getSelect(regResult[1]); 
     if (optObj) { 
      if (obj.checked) { 
       optObj.selectedIndex = orderObj.firstChoice; 
      } else { 
       optObj.selectedIndex = 0; 
      } 
     } 
     orderObj.totalCost(orderObj); 
    } 
}; 

/* 
* Set up events 
*/ 
this.setEvents = function(orderObj) { 
    var spanObj = orderObj.frm.getElementsByTagName('span'); 
    for (var i=0; i<spanObj.length; i++) { 
     var regResult = orderObj.priceReg.exec(spanObj[i].id); 
     if (regResult) { 
      var itemNum = regResult[1]; 
      var chkObj = orderObj.getCheck(itemNum); 
      var selObj = orderObj.getSelect(itemNum); 
      if (chkObj) { 
       chkObj.onclick = orderObj.getCheckEvent(); 
      } 
      if (selObj) { 
       selObj.onchange = orderObj.getSelectEvent(); 
      } 
      if (orderObj.btnTotal) { 
       orderObj.btnTotal.onclick = orderObj.getBtnEvent(); 
      } 
     } 
    } 
}; 
this.setEvents(this); 

/* 
* 
* Grab the prices from the html 
* Required: 
* Prices should be wrapped in span tags, numbers only. 
*/ 
this.grabPrices = function(orderObj) { 
    var spanObj = orderObj.frm.getElementsByTagName('span'); 
    for (var i=0; i<spanObj.length; i++) { 
     if (orderObj.priceReg.test(spanObj[i].id)) { 
      var regResult = orderObj.priceReg.exec(spanObj[i].id); 
      if (regResult) { 
       orderObj.prices[regResult[1]] = parseFloat(spanObj[i].innerHTML); 
      } 
     } 
    } 
}; 
this.grabPrices(this); 

}

+3

这不是一个错误。不要将浮点值用于财务计算:[JavaScript中的精确财务计算。什么是陷阱?](http://stackoverflow.com/questions/2876536/precise-financial-calculation-in-javascript-what-are-the-gotchas)。 –

+0

提问时,请尝试尽可能将问题确定为goog。在这种情况下,您可以从显示值的位置开始,查看它的计算方式,然后将问题简化为“为什么是3 * 4.8!= 14.4?”。 – keppla

回答

3

看一看在Floating Point Guide - 这可以简单地通过计算机如何表示十进制数造成的,而并非是在按你的程序中的错误SE。

解决方案是使用某种十进制数据类型而不是浮点数。 Javascript本身似乎没有一个;请参阅https://stackoverflow.com/questions/744099/javascript-bigdecimal-library进行讨论和一些建议的解决方法。

本指南的Javascript-specific page上有一个链接,指向Javascript的BigDecimal库,可以解决您的问题。

+0

非常感谢您的快速回复,但我在java中并不熟悉。我只是使用这个脚本,我不知道如何修改它。 – ljubo

+2

@ljubo:JavaScript不是Java。你至少应该尝试理解你使用的东西。 –

+0

我想学习太多东西(Java,PHP,ASP,Perl ...),遗憾的是没有足够的时间来完成所有这些:) – ljubo

0

解决此问题的复杂和技术上正确的方法是使用某种内部不使用浮点的小数库,但使用其他人所建议的所有整数。

根据您使用的数字,有时您可以使用浮动工具并将所有内容四舍五入为两位数。例如,在你的情况下:

14.399999999999999.toFixed(2)= 14.40这是你想要的。

+0

谢谢,但我如何修改脚本来实现呢?我不明白java语言...... :( – ljubo

+0

我不知道你的代码或者有办法运行修改后的版本,但总体思路是任何你存储最终结果或显示结果的地方,你将使用toFixed(2)将其舍入到小数点后两位。 – jfriend00

+0

嘿!非常感谢!我解决了您的提示问题! – ljubo