关于浮点:在C ++中截断

Truncation In C++

今天,我试图编写一个程序,用以总结用户输入的整数。例如,如果用户输入683,它将返回6+8+3=17。

但我在代码中遇到了一些奇怪的问题

代码:包括:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
using namespace std;
int computeSum(int num);
int computeInteger(int num, int position);

int main()
{
    int num;
    int sum;
    int total;
    cin >> num;

    total = computeSum(num);

    cout << total;
    return 0;
}

int computeSum(int num)
{
    int position = 10;
    int temp = num;
    double total = 0;
    bool finish = false;

    while(!finish)
    {
        total = total + computeInteger(num, position);

        if(num/ position == 0)
            break;
        position *= 10;
    }

    return total;
}

int computeInteger(int num, int position)
{
    double subtract1 = (double) num / position; //if num = 683 and position = 10 ,     this will get 68.3
    int subtract2 = num / position; //if num = 683 and position = 10 , this will get 68
    double solution = subtract1 - subtract2; //take 68.3 - 68 = 0.3
    return (int)(solution * 10); // return 0.3 * 10 = 3 , but instead of getting 3 this program return 0.3 * 10 = 2
 }

问题

  • 在上面的代码中,当我输入683时,对于函数computeInteger,我得到的不是最后一个数字3,而是返回值2。这很奇怪,因为我认为截断只会删除浮动部分,而不会执行任何向上或向下取整操作。当我测试代码cout << (int)(0.3 * 10)时,我得到了3,但在上面的代码中没有。这让我很困惑。

  • 在浮点中,68.3不是68.3,而是更像68.29999997。阅读有关浮点舍入错误的信息。


    双减1=(双)数字/位置;//如果num=683,position=10,则得到68.3

    这不是完全正确的,0.3不是基数2中的有理数,它非常接近于0.3,但随着数字总是向下取整,为了缩小错误范围,您可以将其强制转换为浮点或长浮点,但这不是一种情况,正如在您的示例中,它始终是0.29,如果您想了解实际发生的情况,必须阅读ab在计算机中的数字表示法中,这里很好地描述了:

    http://en.wikipedia.org/wiki/computer_number_格式

    您遇到的错误是众所周知的错误,也在wiki页面中描述:

    http://en.wikipedia.org/wiki/round-off_错误

    堆栈链接:

    什么是浮点/舍入误差的简单示例?


    此计算不需要使用浮点。将computeSumcomputeInteger替换为:

    1
    2
    3
    4
    5
    6
    7
    int computeSum(int num)
    {
        int sum = 0;
        for (; num; num /= 10)
            sum += num % 10;
        return sum;
    }

    注意:您的代码允许num为负值。如果要支持这些代码,则需要添加其他代码。


    要使浮点运算不受影响,请执行以下操作:

    1
    2
    3
    inline int computeInteger(int num, int position) {
        return (num / (position / 10)) % 10;
    }

    提取数字的常用方法是使用n % 10得到最低数字的值,然后使用n /= 10删除最低数字。重复直到完成。


    如果我必须做类似的事情,我将创建如下递归函数:

    2


    是的,你是对的,你得到2。让我解释一下原因:如果num=683,我将向您展示调试器对ComuteInteger函数中的值所说的内容:

    1
    2
    3
    double subtract1 = (double) num / position;  // substract1=68.299999999999997
    int subtract2 = num / position; // subtract2 = 68
    return (int)(solution * 10); // 2.99999999999997 casted to int will be 2

    这是第一步……