为啥除法后我的 double 或 int 值始终为 0?

Posted

技术标签:

【中文标题】为啥除法后我的 double 或 int 值始终为 0?【英文标题】:Why is my double or int value is always 0 after division?为什么除法后我的 double 或 int 值始终为 0? 【发布时间】:2014-10-30 10:42:18 【问题描述】:

我是 C++ 的新手,我正在为某些图像编辑软件编写百分比增加方法时遇到一些奇怪的行为。

我要做的是给当前像素的 R G 或 B 值,然后除以某个修饰符,然后将它乘以新值以返回百分比增加,相当简单的概念。

但是,每当我运行调试器时,返回值始终为 0,我认为这可能是因为我试图执行在整数上给出负数的操作(或者可能会被零除?),所以我尝试使用 double 来存储计算的输出,但是我没有运气。

我正在努力的代码如下:

int Sliders::getPercentageIncrease(int currPixel, int newValue, int modifier)

    // calculate return value
    double returnVal = (currPixel / modifier) * newValue;

    // Check we are returning a positive integer
    if(returnVal >= 0)
        return (int)returnVal;

    // Return a negative integer value
    return (int)(0 - returnVal);

我在这里做错了什么?

注意:我已经检查了调试器中输入的值,我得到了类似的东西:

currPixel = 30
newValue = 119
modifier = 200

据此,我预计输出为 18(我不关心返回十进制数字)

【问题讨论】:

currPixel / modifier 表达式是整数除法,所以如果modifier 大于currPixel 则结果为零。 您将integers 的除法结果分配为双精度数,因此为 0 尝试将整数更改为双精度数。由于您的结果是双精度结果,因此结果将为 false / 0。 似乎有舍入问题 【参考方案1】:

您当前的计算只涉及整数,因此会受到整数除法的影响(将结果截断为最接近的整数值)。

(currPixel / modifier) * newValue
     |           |
      ---------------integer division e.g. 10/3 = 3, not 3.333

然后将结果转换为 double,但在此之前精度会丢失。

考虑以下几点:

#include <iostream>
using namespace std;

int main() 
    int val1 = 10;
    int val2 = 7;
    int val3 = 9;

    double outval1 = (val1 / val2) * val3;
    double outval2 = ((double)val1 / val2) * val3;
    cout << "without cast: " << outval1 << "\nwith    cast: "<< outval2 << std::endl;

    return 0;

这个输出是:

without cast: 9
with    cast: 12.8571

See it here

请注意,演员表必须应用在正确的位置:

(double)(val1 / val2) * val3 == 9.0      //casts result of (val1/val2) after integer division
(val1 / val2) * (double)val3 == 9.0      //promotes result of (val1/val2) after integer division
((double)val1 / val2) * val3 == 12.8571  //promotes val2 before division
(val1 / (double)val2) * val3 == 12.8571  //promotes val1 before division

由于其他操作数的提升,如果有疑问,您可以转换所有内容,结果代码将是相同的:

((double)val1 / (double)val2) * (double)val3 == 12.8571  

虽然有点冗长。

【讨论】:

【参考方案2】:

由于三个参数都是整数,所以计算结果

double returnVal = (currPixel / modifier) * newValue;

将始终被截断。将 cast 添加到 (double) ,结果应该没问题。简单地说:

double returnVal = ((double)currPixel / modifier) * newValue;

如果您只在括号前设置强制转换,则除法的结果将保持为整数。

【讨论】:

在分割完成之前添加演员表(double)(1/2) 仍然是 0【参考方案3】:

只要所有值都在一个范围内,比如说,小于 1000 并且大于(或等于)0(这在颜色值上很常见),请执行类似的操作

int returnVal = (currPixel * newValue) / modifier

不需要双打;它甚至会加速代码。 不用说,modifier不应该是零。

【讨论】:

好吧,@ 987654323@ AFAIK。差别不大。 现有代码在返回时将双精度数舍入为 int。不过,负输入可能存在一些舍入差异。 这里缺少的是函数行为的准确规范。非整数结果应该四舍五入还是截断?由于函数的返回值是一个 int,所以我们大多数时候都会出错。上面的计算并没有使情况变得更糟,它是确定性的,而且速度很快。【参考方案4】:

这样做:

// calculate return value
double returnVal = (static_cast<double>(currPixel) / modifier) * newValue;

或者这个:

double returnVal = (currPixel / static_cast<double>(modifier)) * newValue;

如您所知,将首先执行operator /,然后执行operator *。我已将/ 的操作数之一转换为double,因此将执行除法double。现在,* 的左操作数将是double(因为/ 产生double),并且乘法也将执行double。为了清楚和正确,你可以写:

double returnVal = (static_cast<double>(currPixel) / static_cast<double>(modifier)) * static_cast<double>(newValue);

或者简单地说:

double returnVal = (double(currPixel) / (double)modifier) * (double)newValue;

但是,以下是错误的:

double returnVal = (double)(currPixel / modifier) * /*(double)*/ newValue;

因为除法将只执行int!就像:

double x = 10/3;

您需要的地方(任一):

double x = 10.0/3;
double x = 10/3.0;
double x = (double)10/3;

【讨论】:

【参考方案5】:

转换为 double 应该可以修复错误。

double returnVal =  (double ) (currPixel) / (modifier) * newValue;

查看类型转换规则typecasting rules in c。

【讨论】:

以上是关于为啥除法后我的 double 或 int 值始终为 0?的主要内容,如果未能解决你的问题,请参考以下文章

为啥字节和短除法会在 Java 中产生 int?

java做除法运算,为啥除不开时也会得到整数呢

Swift 3:致命错误:Double 值无法转换为 Int,因为它是无限的或 NaN

C++ 中的除法舍入

Int除法:为啥1/3 == 0的结果?

int除法:为啥1/3 == 0的结果?