假設有一個鐘擺從 -1 擺動到 1:

這個鐘擺等價于 SIGN。還想象一下,這個鐘擺在 60fps 的更新回圈中擺動得非常快。
這可能是我的代碼:
let angle = 0
function update() {
angle = .1
pendulum.angle = Math.sin(angle)
requestAnimationFrame(update)
}
update()
沒關系。我想要的是檢測這個鐘擺最接近 -1 或 1 的點。有人可能認為你可以寫:
if (pendulum.angle == -1 || pendulum.angle == 1) {
console.log('pendulum is at it\'s maximum')
}
然而,它并不是這樣作業的:如果鐘擺的速度非常快,它可能會完全錯過 -1 或 1!另一個看似可能的解決方案是檢測鐘擺是否在某個范圍內,如果是,則發出訊息:
if (pendulum.angle < -0.9 || pendulum.angle > 0.9) {
console.log('pendulum is at it\'s maximum')
}
...但是如果速度真的非常快呢?如果它錯過了這些范圍怎么辦?
角度越來越大受到程式幀速率的限制 - 所以它旋轉得越快,它跳過的空間就越多。
這導致了一個問題:我可以使用什么公式來確定范圍應該有多大 - 基于它的速度?
任何幫助,將不勝感激。
uj5u.com熱心網友回復:
計算當前值sin以及前后值的值。如果您的sin值更接近-1或1小于前面和后續值的值,那么您是最接近的,請進行日志記錄。
function update() {
lastanglemag = Math.abs(Math.sin(angle)); // Get the preadjustment magnitude
angle = .1
pendulum.angle = Math.sin(angle)
currentanglemag = Math.abs(pendulum.angle) // Get current magnitude
// If current magnitude is larger than both neighbors, we're at a maximum
if (currentanglemag > lastanglemag && currentanglemag > Math.abs(Math.sin(angle 0.1))) {
console.log("pendulum is at its maximum")
}
requestAnimationFrame(update)
}
update()
優化只計算一個新的sinper update(一個用于next angle),快取其他值,以減少 2-3 個sin呼叫update到一個,留給讀者作為練習(我不想引入任何額外的持久狀態以及相關的復雜性,實際上,對于任何基于 GUI 的東西,1-2 次額外sin計算的成本是沒有意義的;用戶無論如何都看不到以納秒為單位的延遲)。
uj5u.com熱心網友回復:
使用 d/dx sin(x) = cos(x),可以將另一個答案簡化為
function update() {
lastangle_d = Math.cos(angle); // Get the preadjustment derivative
angle = .1
pendulum.angle = Math.sin(angle);
currentangle_d = Math.cos(angle); // Get current derivative
// If signum of current and previous derivatives differ, we've passed a maximum
if (Math.sign(lastangle_d) !== Math.sign(currentangle_d)) {
console.log("pendulum is at its maximum")
}
requestAnimationFrame(update);
}
update();
如果有人真的想破解,if (lastangle_d*currentangle_d < 0)也可以這樣做。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/481664.html
標籤:javascript
