[問題] 如何限制一個值在設定範圍內

看板C_and_CPP作者 (Syatoyan)時間9年前 (2016/07/28 23:50), 9年前編輯推噓9(9010)
留言19則, 6人參與, 最新討論串1/1
開發平台(Platform): C語言 額外使用到的函數庫(Library Used): 問題(Question): 輸入一個值 將這個值限制在設定的範圍內 然後輸出 程式碼(Code): double InVal, MinVal, MaxVal; double OpVal; while(InVal > MaxVal) { InVal = InVal - MaxVal + MinVal; } while(InVal < MinVal) { InVal = InVal - MinVal + MaxVal; } OpVal = InVal; 補充說明(Supplement): 這種方法 當InVal的值很大 可是MinVal 和 MaxVal的區間很小的時候 會卡在while迴圈好久 不知道還有沒有什麼更好的寫法可以縮短時間的 補充1:用角度 -360~360來看 360度 = -360度 所以 InVal = 361 MinVal = -360 MaxVal = 360 可以得到 OpVal = -359 因為MinVal不一定為0 所以沒辦法直接用取餘數的方法處理 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 218.166.80.62 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1469721030.A.390.html

07/29 00:03, , 1F
不太懂你的用意 但一般InVal>MaxVal會讓InVal=MaxVal
07/29 00:03, 1F

07/29 00:46, , 2F
把最小值用offset移到0,Range=Max-Min。
07/29 00:46, 2F

07/29 00:49, , 3F
InVal=(int)(InVal/Range) + 餘數,不知道負數會怎樣
07/29 00:49, 3F

07/29 00:55, , 4F
用%,外面包一層另外判斷負數?
07/29 00:55, 4F

07/29 01:09, , 5F
OpVal = floor((InVal-offset)/Range) + offset;
07/29 01:09, 5F

07/29 01:10, , 6F
這樣應該比原方法快很多,而且正負數通用。剛剛腦殘了。
07/29 01:10, 6F

07/29 01:20, , 7F
上面那串無視吧,半夜腦袋太鈍了...
07/29 01:20, 7F

07/29 01:25, , 8F
OpVal = InVal - floor((InVal-Offset)/Range) * Range;
07/29 01:25, 8F

07/29 01:28, , 9F
這樣結果才會是正確的。
07/29 01:28, 9F

07/29 01:29, , 10F
floor()在math.h裡。
07/29 01:29, 10F
感謝 將程式碼改成 Range = MaxVal - MinVal; OpVal = InVal - floor((InVal - MinVal) / Range) * Range; 確實可以得到一樣的結果 另外 提供用KeilC 跑8051 測試執行時間的結果 輸入區間 [-5, 5] 輸入數值 5 50 500 原始方法執行時間(us) 3.6 14 97.2 新方法執行時間(us) 4.8 7.6 8.0

07/29 08:36, , 11F
是說這樣用double感覺很怪
07/29 08:36, 11F
原本是用float來處理擷取資料的問題,可是小數點下四位的精準度不足, 所以才改用double來試試看。

07/30 00:15, , 12F
有 fmod 浮點數取餘數的函式可以用
07/30 00:15, 12F

07/30 00:22, , 13F
將角度限定在0~360個人是會這麼寫:fmod(fmod(deg,360)+
07/30 00:22, 13F

07/30 00:22, , 14F
360,360)
07/30 00:22, 14F

07/30 01:36, , 15F
可是負數mod正數還是負數,他的MinVal跟InVal可能<0
07/30 01:36, 15F

07/30 07:05, , 16F
限定在-3~10之間:fmod(fmod(x,13)+13,13)-3
07/30 07:05, 16F
這個方法好像也不錯 call了兩次fmod 上面的是call一次floor 等我找個時間再來補充這個方法的執行時間 再來比較看看

07/30 15:25, , 17F
x 要先加3
07/30 15:25, 17F
測試的結果 正確的算式是 Range = MaxVal - MinVal; OpVal = fmod(fmod(InVal - MinVal, Range) + Range, Range) + MinVal; 同樣用KeilC 測試時間 floor的方法 需要 8us fmod的方法 需要 12us ※ 編輯: syatoyan (223.139.136.48), 08/01/2016 18:27:24

08/01 20:06, , 18F
這個差距是因為 floor 法做一次除, fmod 法做兩次除
08/01 20:06, 18F

08/01 20:06, , 19F
除是四則運算裡最花時間的了
08/01 20:06, 19F
文章代碼(AID): #1NcYd6EG (C_and_CPP)