调整浮点数以满足条件:abs(浮点数) <= 0.5?



我有一个任意大小的float向量。我想调整浮点数,使其满足条件abs(float) <= 0.5.小数部分虽然可以与原始值不同,但要保留,因此设置&;x = 0.5&;是不正确的。如果浮点数接近整数,则丢弃它(输入的浮点数不能是整数或在任意精度范围内接近1)。

这是我写的,但是代码看起来有些分支。我想知道是否有办法使它更优雅/高效,或者有一些关键的东西我可能错过了。

输入:浮动

输出:调整浮动x,使fabs(x) <= 0.5

整数部分的例子

  1. -5.3→-0.3(取小数部分,如果abs(小数)<= 0.5)
  2. -5.8→0.2(加上最接近的整数,向上舍入,相对于绝对值)。
  3. 5.3→0.3
  4. 5.8→-0.2(减去,但四舍五入)
  5. -5.5→-0.5(此处保留符号)
  6. 5.5→0.5(此处保留符号)

仅包含小数部分的示例

  1. 0.3→0.3

  2. 0.8→-0.2(减去1)

  3. -0.3→-0.3

  4. -0.8→0.2(加1)

角情况下

  1. 任意整数->0
  2. 0.5→0.5
  3. -0.5→-0.5
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <random>
#include <vector>
float scale(float x)
{
const auto integerPart = std::abs(static_cast<std::int32_t>(x));
const auto fractionalPart = std::fabs(x - static_cast<std::int32_t>(x));
if (x < 0) {
if (integerPart == 0) {
if (fractionalPart > 0.5) {
x += 1;
}
}
else {
x += integerPart + (fractionalPart > 0.5 ? 1 : 0);
}
}
else {
if (integerPart == 0) {
if (fractionalPart > 0.5) {
x -= 1;
}
} else {
x -= integerPart + (fractionalPart > 0.5 ? 1 : 0);
}
}
return x;
}
int main() {
std::vector<float> floats(10000);
static std::default_random_engine e;
static std::uniform_real_distribution<float> distribution(-5, 5);
std::generate(floats.begin(), 
floats.end(), 
[&]() { return distribution(e); });
for (std::size_t i = 0; i < floats.size(); ++i) {
floats[i] = scale(floats[i]);
}
std::cout << std::boolalpha 
<< std::all_of(floats.cbegin(),
floats.cend(),
[&](const float x){ return std::fabs(x) <= 0.5; }) << "n";
}

符号保留在这里是相关的,如果小数部分超过0.5,结果值的符号是反转的。

谢谢。

这只是remainder函数,除了当结果恰好是±½时使用的符号,可以通过从输入复制符号来调整:

double ModifiedRemainder(double x)
{
double y = std::remainder(x, 1);
return std::fabs(y) == .5 ? std::copysign(y, x) : y;
}

您可以使用floor函数来减少分支的数量:

#include <iostream>
#include <cmath>
float scale(float x) {
bool neg = std::signbit(x);
x -= std::floor(x + 0.5);
if (!neg && x == -0.5) {
return 0.5;
} else {
return x;
}
}
int main() {
std::cout << "-1.23 " << scale(-1.23) << std::endl;
std::cout << "-0.5 " << scale(-0.5) << std::endl;
std::cout << "0.123 " << scale(0.123) << std::endl;
std::cout << "0.5 " << scale(0.5) << std::endl;
std::cout << "1.23 " << scale(1.23) << std::endl;
}
-1.23 -0.23
-0.5 -0.5
0.123 0.123
0.5 0.5
1.23 0.23

相关内容

  • 没有找到相关文章

最新更新