从非均匀范围转换浮点数
Posted
技术标签:
【中文标题】从非均匀范围转换浮点数【英文标题】:Convert float number from nonuniform ranges 【发布时间】:2017-04-01 02:57:31 【问题描述】:所以我遇到了这个相对简单的问题,想知道它的解决方案是否已经存在。
我必须将一个值从一个范围转换为另一个范围。如果只有一个范围,像这样:
-30.0, 30.0 -> 25.0, 50.0
这很容易。 但我有一组范围:
-30.0, -20.0 -> 25.0, 30.0
-20.0, 0.0 -> 30.0, 40.0
0.0, 30.0 -> 40.0, 50.0
一种解决方案是对每次访问进行线性搜索。 另一种解决方案是使范围具有相等的长度,以便可以直接映射输入值。
有人知道比线性搜索更好的解决方案吗?或者是否已经存在执行这种转换的容器?
非常感谢。
【问题讨论】:
范围可以重叠吗? @user1034749 不,它们不重叠。 @user1034749:更正 - 输入集或输出集中的范围不重叠。但是,不幸的是,输入和输出的范围确实如此。 IE。 -30.0, -20.0 转换为 -25.0, -20.0。 我的解决方案只依赖于输入“重叠”,输出和输入的关系并不重要 【参考方案1】:我假设范围不能重叠。 (域和范围)
我建议对范围进行排序。
这样,您可以使用O(log n)
查询范围。
替代方法
在某些输入模式中,这种方法可能是合适的:-
转换这个:-
-30.0, -20.0 -> 25.0, 30.0
-20.0, 0.0 -> 30.0, 40.0
0.0, 30.0 -> 40.0, 50.0
变得更加统一 :-
float [] inputRange = -30,-20, -10,0 ,10 ,20 ,30;
float [] outputRange = 25 ,30 ,*35*,40,*43.3333*,*43.6667*,50;
//* is a pre-calculated
那么你可以只使用O(1)
查询。
缺点:-
浪费更多内存 输入必须捕捉一些不太小的值。 (本例 = 10)【讨论】:
【参考方案2】:作为@javaLover 回复,而不是线性 - O(n) 操作,
当 n - 范围数时,您可以通过 O(log n) 找到合适的范围
操作,例如std::map
:
#include <utility>
#include <map>
#include <algorithm>
#include <iostream>
int main()
using Range = std::pair<double, double>;
struct RangeLess
bool operator()(const Range &a, const Range &b) const
return a.first < b.first && a.second < b.second;
;
using RangeMap = std::map<Range, Range, RangeLess>;
const RangeMap ranges_map =
-30.0, -20.0, 25.0, 30.0,
-20.0, 0.0, 30.0, 40.0,
1.0, 30.0, 40.0, 50.0,
;
auto map_point = [&ranges_map](double x) -> double
const Range x_range = x, x;
auto it = ranges_map.find(x_range);
if (it == ranges_map.end())
return x;
else
const Range &in = it->first;
const Range &out = it->second;
return (x - in.first) / (in.second - in.first) * (out.second - out.first) + out.first;
;
const double patterns[] = -40, -30, -25, -20, 0.5, 5, 40;
for (auto &&x : patterns)
std::cout << x << " -> " << map_point(x) << "\n";
【讨论】:
非常优雅的解决方案。 (1)unordered_map
可以用吗? (2) 抱歉,我误解了您的“非重叠”问题。不幸的是,from->to 范围可以重叠。【参考方案3】:
这是对@user1034749 提出的解决方案的详细说明。它使用 std::set 和一个包含两对值的类。
template<class SRC, class DST>
class Range
public:
std::pair<SRC, SRC> src_range;
std::pair<DST, DST> dst_range;
bool operator<(const Range& rhs) const
return (src_range.first < rhs.src_range.first) && (src_range.second < rhs.src_range.second);
Range(SRC src_first, SRC src_second,
DST dst_first, DST dst_second)
: src_range(src_first, src_second),
dst_range(dst_first, dst_second)
Range()
: src_range(0, 0),
dst_range(0, 0)
Range(SRC value)
: src_range(value, value),
dst_range(value, value)
;
bool mapping_test()
// Mapping
std::set<Range<double,double>>
z = -30.0, -20.0, -10.0, -5.0,
-20.0, 0, -5.0, 5.0,
0, 10.0, 5.0, 8.0;
// Find range that contains this value
Range<double,double> f8.0;
auto d = z.find(f);
if(d != z.end())
std::cout << "Found " << (*d).dst_range.first
<< ","
<< (*d).dst_range.second
<< "\n";
return true;
在这种情况下,可以找到相关值的范围,包括源范围和目标。在 std::set 容器中查找是 log(n) 复杂度。
【讨论】:
以上是关于从非均匀范围转换浮点数的主要内容,如果未能解决你的问题,请参考以下文章