c++ - 四舍五入一个整数,使其乘以一个 float 返回一个整数

标签 c++ algorithm math scaling

我正在开发一个图像缩放应用程序,我得到了一个缩放比率和一个矩形。我需要将矩形与比率相乘,但还要确保生成的矩形仅由整数组成(即没有 float )。如果不是,我想扩展源 Rectangle 以便满足上述条件。

目前我正在暴力破解它(下面的代码)。但我很确定有一种方法可以使用巧妙的数学来做到这一点。

RECT AdjustRectWholeNumber(RECT SrcRect, float ratio)
{
    RECT adjustedRect = SrcRect;
    while (!isWholeNumber(adjustedRect.left * ratio))
    {
        adjustedRect.left--;
    }
    while (!isWholeNumber(adjustedRect.top * ratio))
    {
        adjustedRect.top--;
    }
    while (!isWholeNumber(adjustedRect.right * ratio))
    {
        adjustedRect.right++;
    }
    while (!isWholeNumber(adjustedRect.bottom * ratio))
    {
        adjustedRect.bottom++;
    }
    return adjustedRect;
}

示例:给定矩形 (78,188,1068,790) 和比率 1.25,它应该返回 (76, 188, 1068, 792)

推理:如果我将 (78,188,1068,790) 乘以 1.25,它会得到 (97.5, 188, 1068, 987.5)。这并不理想,因为如果我将缩放后的矩形四舍五入(向上或向下),我会失去精度,这会在屏幕上显示为小的损坏伪影。就好像我们扩展源矩形,这样在乘以比例因子后我们得到所有整数,没有精度损失,因此没有看到损坏。

注意:缩放比例保证能产生整数

感谢任何帮助!

编辑:根据要求为 isWholeNumber 添加代码

bool isWholeNumber(float f)
{
    if (floor(f) == f)
        return true;
    return false;
}

为了澄清,让我们假设我将得到的唯一比率是 (1.25, 1.5, 1.75, 2.0, 2.25)

最佳答案

我认为一般情况下,您发布的问题没有很好的解决方案。并非所有“好”分数都精确表示为 float (例如 4/3 没有)。通常只有那些以 2 为分母的分数才能精确表示。如果您尝试按原样对“坏”分数使用 float 近似值,您将得到一个分母约为 2^-20 的分数,即 左右10^-6 拟合没有意义。因此,显而易见的建议是使用一些明确的自定义类型将分数表示为明确的(整数)分母和分母。如果你有明确的分母值,任务就变得微不足道了。或者,如果您确定

the only ratios I will ever get are (1.25, 1.5, 1.75, 2.0, 2.25)

你可以有一个简单的函数来匹配值并判断分母是 12 还是 4。如果您有更多可能的值,但所有分数的分母都是 2 的幂,您也可以考虑使用 frexp/frexpf得到指数(分母的2次方)

所以现在当你有了一个整数分母时,一切都变得非常简单:你只需要找到一个能被它整除的数字。您可以使用整数除法和乘法来完成(假设您的值为正):

int roundDown(int value, int denominator) {
    return (value / denominator) * denominator;
}

int roundUp(int value, int denominator) {
    return ((value + denominator - 1) / denominator) * denominator;
}

关于c++ - 四舍五入一个整数,使其乘以一个 float 返回一个整数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44312334/

相关文章:

c++ - 为什么在实现链接列表时 "delete at head"不能正常工作?

c++ - 从 std::ostream 继承(以避免重写相同的旧内容)...?

c++ - 这段代码会做什么? (内存管理)

algorithm - Haskell 粒子模拟 - 计算粒子的速度

algorithm - A* 如何搜索图表?

algorithm - 如何证明二项式系数是2的n次方的渐近大theta?

c++ - 向着色器添加线不会画任何东西

algorithm - 图像识别的良好神经网络拓扑和训练方法

ruby-on-rails - Ruby on Rails 上的正态分布随机变量

java - 两个 3D vector 之间的角度