2011-09-08 53 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