有很多與此代碼的問題。
首先,像這樣在循環中添加浮點數會增加浮點格式中的二進制錯誤,直到它們在輸出中變得明顯。嘗試運行這段代碼:
var a = [];
for (var i = 0; i < 2 * Math.PI; i += 0.02)
a.push(i);
$('#output').html(a.join('<br/>'));
http://jsfiddle.net/b9chris/AwT5c/
看看它生成的值。這可能不是你所期望的。這些瘋狂的數字是浮點數存儲方式的結果 - 小數部分存儲爲二進制小數,所以1/2 + 1/4 + 1/8 + ...。 0.02不能用這種格式精確表示,所以系統接近它,然後當它返回時將該值舍入爲10個小數,覆蓋了被篡改的基礎值。但是這些增加是用二進制完成的,最終這些近似值加起來並且揭示了這個問題。
的解決方案是不是與整數循環,儘可能晚地劃分:
http://jsfiddle.net/b9chris/AwT5c/1/
其次,你的循環條件包括:總是返回相同結果的操作。這會浪費CPU時間--for循環將不斷重新計算2 * Math.PI的值,以便每個循環都得到完全相同的結果。您可以通過將其存儲在一個變量中並針對該變量運行循環來解決此問題。
你可能不明白Array.push()是如何工作的。你傳遞一個值來推送它,並自動將它分配給數組中的下一個索引。因此,這與在它1個值的陣列上運行:
a.push([5, 10]);
在索引1(未5)添加一個值,並且該值是本身有2項數組,[5, 10]
。所以你這樣做的地方:
d1.push([i, 1]);
var d = d1[i][1];
例如,您正在索引0處添加一個值,然後嘗試在索引爲0.02處將其取出。由於您的目標是通過索引直接訪問它們,因此使用push並不是很安全,然後假定索引與循環計數器中的內容匹配(例如,如果數組已經添加了值,該怎麼辦)。而是直接通過索引來分配,這在Javascript中是允許的。
最後,你應該避免像這樣將所有東西都轉移到全局範圍內 - 使用var關鍵字將它們的範圍限制在本地。
var d1 = [];
var d2 = [];
var d3 = [];
var inverseStep = 50; // 1/.02
var l = 2 * Math.PI * inverseStep;
for (var i = 0; i < l; i++) {
var ix = i/inverseStep;
d1[i] = [ix, 15+Math.sin(5*ix)];
d2[i] = [ix, 10+Math.sin(4*ix)];
var d = d1[i][1] + d2[i][1];
d3[i] = [ix, d];
}
$('#output').html(d3.join('<br/>'));
http://jsfiddle.net/b9chris/AwT5c/3/
聽起來像'D1 [I]'或'D2 [I]'不存在。如果'd1 [i]'沒有定義,當你push()時你不能'undefined [1]' –
,你的元素會有整數索引,比如'2'。但是,你的i變量不是一個整數,它的東西就像'0.04' – goat