![](/img/trans.png)
[英]Qt4: How to change the default values (range, value, single step size) for QSpinBox for new instances?
[英]Map a range of values to a single value
我需要將介於lowerBound
和upperBound
之間的值映射到某個值。
說明性示例:
例如,假設我有GPS系統,用戶訂閱了它。 該系統能夠為我提供用戶與某一點的距離。 根據用戶的距離,我想為他們分配一個ID。
從而遠離用戶
1
到100
獲得ID: 8.4
101
到200
獲得ID: 7.2
201
至300
獲得ID: 3.6
401
到600
獲得ID: 4.1
等等...
我的方法:
所以我做了什么,我通過初始化它創建了一個std::map
如下:
std::map<int, double> distanceToIdMap;
distanceToIdMap =
{
{100, 8.4},
{200, 7.2},
{300, 3.6},
};
然后我使用此代碼獲取給定距離的ID:
double roundUpToHundred = std::ceil(realDistance / 100.0) * 100;
double powerForDistance = distanceToIdMap.at(roundUpToHundred);
然而,我的方法分解為401
到600
距離,因為天花板到最接近的百分之400+
距離我得到的值500
我沒有在地圖中的條目。 當然,簡單的解決方案是在distanceToIdMap
添加500
條目,但這不是我想要處理這個問題的方法。
我希望有一個帶{(lowerbound, upperbound) , correspondingID}
ID {(lowerbound, upperbound) , correspondingID}
結構的地圖,這樣我就可以解決ID覆蓋距離超過100米的情況。 並且給定的可以檢查lowerBound
< realDistance
< upperBound
然后提供ID。
它聽起來像std :: lower_bound的用例。 請注意, lower_bound
是正確的實現,而不是upper_bound
。 此代碼編譯和工作。 map
不需要排序,因為它已經排序。 這應該在O(log(N))中運行 。
你需要抓住異常......
#include <iostream>
#include <algorithm>
#include <map>
#include <stdexcept>
using namespace std;
std::map<int, double> distanceToIdMap =
{
{100, 8.4},
{200, 7.2},
{300, 3.6},
{600, 4.1}
};
double Distance(int user)
{
auto x = std::lower_bound(distanceToIdMap.begin(), distanceToIdMap.end(), std::pair<const int,double>(user,0));
if (x == distanceToIdMap.end()) throw std::runtime_error("can't find");
return x->second;
}
int main()
{
for(int user=25;user < 650;user+=25)
{
cout << user << " " << Distance(user) << std::endl;
}
return 0;
}
輸出:
sh-4.3# g++ -o main *.cpp -std=c++11
main
sh-4.3# main
25 8.4
50 8.4
75 8.4
100 8.4
125 7.2
150 7.2
175 7.2
200 7.2
225 3.6
250 3.6
275 3.6
300 3.6
325 4.1
350 4.1
375 4.1
400 4.1
425 4.1
450 4.1
475 4.1
500 4.1
525 4.1
550 4.1
575 4.1
600 4.1
terminate called after throwing an instance of 'std::runtime_error'
what(): can't find
Aborted (core dumped)
sh-4.3# main
嘗試upper_bound
:
auto upper = distanceToIdMap.upper_bound( 50 );
std::cout << "value:" << upper->second << std::endl;
使用std::map::lower_bound
和boost::optional
,您可以執行以下操作:
const std::map<int, boost::optional<double>> distanceToIdMap =
{
{0, boost::none},
{100, 8.4},
{200, 7.2},
{300, 3.6},
{400, boost::none},
{600, 4.1}
};
for (auto v : {-10, 50, 99, 100, 101, 250, 350, 500, 601})
{
auto it = distanceToIdMap.lower_bound(v);
if (it != distanceToIdMap.end() && it->second) {
std::cout << v << " " << *it->second << std::endl;
} else {
std::cout << v << " None" << std::endl;
}
}
那么避免使用地圖呢?
std::vector<std::pair<double, double>> table =
{
{0, 0},
{94.5, 2.1},
{314.4, 4.7}
} ;
double distance = ...
double value = std::upper_bound(table.begin(), table.end(), std::pair(distance, 0)) ;
缺點:必須正確訂購表格。
這是一個簡單的解決方案:
int mapdistance[] = {100,200,300};
double mapid[] = {8.4,7.2,3.6};
double dist=0;
for(int i=0;i<sizeof(mapdistance)/sizeof(int);i++) {
dist += mapdistance[i];
if (realdistance<=dist) return mapid[i];
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.