如何将一个范围内的值插入到另一个范围内
How to interpolate a value in one range into another
我有 2 个双精度值,可以从起始值 62.243
到结束值 79.495
。我还有另外 2 个双精度值,可以从起始值 4.456
到结束值 7.687
.
double start_1 = 62.243;
double end_1 = 79.495;
double start_2 = 4.456;
double end_2 = 7.687;
现在,如果我在 start_1
和 end_1
之间选择一个值,我想将相同的值插入到 start_2
和 end_2
之间的值。
问题:
如何在 C++ 中实现下面的功能,它可以完成我上面描述的事情?
double InterpolateAValue(const double start_1, const double end_1, const double start_2, const double end_2, double value_between_start_1_and_end_1) {
// How to get a value between start_2 and end_2 which matches the position of value_between_start_1_and_end_1 in the range of `start_1` and `end_1`
};
我认为上面的函数应该可以通过下面的单元测试。
EXPECT_DOUBLE_EQ(40.0, InterpolateAValue(10.0, 20.0, 30.0, 50.0, 15.0));
std::lerp 似乎在做我需要的事情,但不完全是。我在 C++11 上。我这里的类型是double
。我也可以选择 float
s,但希望了解双打如何影响数学也是问题的一部分。
对于一个数字 value_between_start_1_and_end_1
,
lambda = (value_between_start_1_and_end_1 - start_1) / (end_1 - start_1)
告诉您您沿着 1
线走了多远。 0 表示您在 start_1
,1 表示您在 end_1
。
然后使用
start_2 + lambda * (end_2 - start_2)
沿2
线得到相应的位置。我将计算分为两个阶段,但除了放弃调试的便利性之外,您还可以在一个步骤中合并。
就我个人而言,我总是为此使用 double
s。由于意外的类型转换,float
在现代系统上甚至可能更慢。当然你需要检查 start_1
和 end_1
是否不同。
从 C++20 开始有 std::lerp
.
Computes a+t(b−a), i.e. the linear interpolation between a and b for the parameter t (or extrapolation, when t is outside the range [0,1]).
它完成了您想要的一半。你的 t
是 t = ( value - start_1) / (end_1 - start_1)
。因此你可以做
#include <cmath>
double InterpolateAValue(double start_1,double end_1,double start_2, const double end_2, double value) {
return std::lerp(start_2, end_2, (value - start1) / (end_1 - start_1));
}
我有 2 个双精度值,可以从起始值 62.243
到结束值 79.495
。我还有另外 2 个双精度值,可以从起始值 4.456
到结束值 7.687
.
double start_1 = 62.243;
double end_1 = 79.495;
double start_2 = 4.456;
double end_2 = 7.687;
现在,如果我在 start_1
和 end_1
之间选择一个值,我想将相同的值插入到 start_2
和 end_2
之间的值。
问题:
如何在 C++ 中实现下面的功能,它可以完成我上面描述的事情?
double InterpolateAValue(const double start_1, const double end_1, const double start_2, const double end_2, double value_between_start_1_and_end_1) {
// How to get a value between start_2 and end_2 which matches the position of value_between_start_1_and_end_1 in the range of `start_1` and `end_1`
};
我认为上面的函数应该可以通过下面的单元测试。
EXPECT_DOUBLE_EQ(40.0, InterpolateAValue(10.0, 20.0, 30.0, 50.0, 15.0));
std::lerp 似乎在做我需要的事情,但不完全是。我在 C++11 上。我这里的类型是double
。我也可以选择 float
s,但希望了解双打如何影响数学也是问题的一部分。
对于一个数字 value_between_start_1_and_end_1
,
lambda = (value_between_start_1_and_end_1 - start_1) / (end_1 - start_1)
告诉您您沿着 1
线走了多远。 0 表示您在 start_1
,1 表示您在 end_1
。
然后使用
start_2 + lambda * (end_2 - start_2)
沿2
线得到相应的位置。我将计算分为两个阶段,但除了放弃调试的便利性之外,您还可以在一个步骤中合并。
就我个人而言,我总是为此使用 double
s。由于意外的类型转换,float
在现代系统上甚至可能更慢。当然你需要检查 start_1
和 end_1
是否不同。
从 C++20 开始有 std::lerp
.
Computes a+t(b−a), i.e. the linear interpolation between a and b for the parameter t (or extrapolation, when t is outside the range [0,1]).
它完成了您想要的一半。你的 t
是 t = ( value - start_1) / (end_1 - start_1)
。因此你可以做
#include <cmath>
double InterpolateAValue(double start_1,double end_1,double start_2, const double end_2, double value) {
return std::lerp(start_2, end_2, (value - start1) / (end_1 - start_1));
}