代码之家  ›  专栏  ›  技术社区  ›  Sanskriti

在C中,为什么10/3给出3.000,而它应该给出3.333?(保持10和3的变量被声明为“双”)

  •  1
  • Sanskriti  · 技术社区  · 1 年前

    我正在尝试求解分数背包,我的代码是:

    #include <stdio.h>
    
    struct item {
        int index;
        double profit;
        double weight;
        double pw_ratio;
    };
    
    void sort(struct item a[], int n) {
        
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (a[i].pw_ratio > a[j].pw_ratio) {
                    int temp = a[i].pw_ratio;
                    a[i].pw_ratio = a[j].pw_ratio;
                    a[j].pw_ratio = temp;
                    
                    temp = a[i].profit;
                    a[i].profit = a[j].profit;
                    a[j].profit = temp;
                    
                    temp = a[i].weight;
                    a[i].weight = a[j].weight;
                    a[j].weight = temp;
                }
            }
        }
        
        printf("Sorted items: \n");
        for (int i = 0; i < n; i++) {
            printf("%d\t%lf\t%lf\t%lf\n", a[i].index, a[i].pw_ratio,
                   a[i].profit, a[i].weight);
        }
    }
    
    int main() {
        int n;
        printf("Enter the number of items: ");
        scanf("%d", &n);
        int capacity;
        printf("Enter the capacity of knapsack: ");
        scanf("%d", &capacity);
        struct item a[n];
        for (int i = 0; i < n; i++) {
            a[i].index = i + 1;
            printf("Enter profit of item%d: ", i + 1);
            scanf("%lf", &a[i].profit);
            printf("Enter weight of item%d: ", i + 1);
            scanf("%lf", &a[i].weight);
            a[i].pw_ratio = (double)a[i].profit / a[i].weight;
            //printf("Profit-weight ratio: %lf", a[i].pw_ratio);
        }
        sort(a, n);
        //solve(a, n);
    }
    

    当我输入利润=10,权重=3时 sort 函数的输出打印 pw_ratio 3.000 (而不是 3.333 )然而,下一个迭代项(即第二项)给出了完美的十进制值。

    我试过调试,打印时 pw_ratio main 函数本身(我接受输入的地方 profit weight )这是绝对正确的,即10/3会给出3.33,20/9会给出2.222,依此类推。这里的问题是什么,如何解决?

    3 回复  |  直到 1 年前
        1
  •  4
  •   Ted Lyngmo    1 年前

    在里面 int temp = a[i].pw_ratio; 将比率存储在 int 变量,有效地截断它 a[j].pw_ratio = temp; 则不恢复原始值。

    整个交换过程可以通过交换 struct item 一次,然后将在所有地方使用正确的类型。

    if (a[i].pw_ratio > a[j].pw_ratio) {
        struct item temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    
        // swap back index
        int idx = a[i].index;
        a[i].index = a[j].index;
        a[j].index = idx;
    }
    
        2
  •  4
  •   Paul Hankin    1 年前

    您的排序函数使用 temp int 变量,以便在交换时临时存储值。这会导致某些值被截断为 int .你也不交换 index 尽管目前还不清楚这是一个错误还是故意的。

    注意,您可以使用标准库函数 qsort 对数组进行排序。除了更正确、代码更少之外,当数组变长时,它也会更有效率。

        3
  •  2
  •   chqrlie    1 年前

    这个 sort 函数使用 int 变量执行值交换,导致 double 值到 int ,有效地截断了值。您应该交换结构并重建 index 排序后的成员。

    还要注意,您的排序方法不起作用:您应该只比较具有索引值的元素 i j 使得 i < j

    以下是修改后的版本:

    void sort(struct item a[], int n) {
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                if (a[i].pw_ratio > a[j].pw_ratio) {
                    struct item temp = a[i];
                    a[i] = a[j];
                    a[j] = temp;
                }
            }
        }
    
        for (int i = 0; i < n; i++) {
            a[i].index = i + 1;
        }
        
        printf("Sorted items: \n");
        for (int i = 0; i < n; i++) {
            printf("%d\t%f\t%f\t%f\n", a[i].index, a[i].pw_ratio,
                   a[i].profit, a[i].weight);
        }
    }
    

    您也可以使用 qsort 定义于 <stdlib.h> :

    #include <stdlib.h>
    
    int compare_ratios(const void *a, const void *b) {
        const struct item *aa = a;
        const struct item *bb = b;
        int cmp = (aa->pw_ratio > bb->pw_ratio) - (aa->pw_ratio < bb->pw_ratio);
        // implement stable sorting:
        //     keep elements that compare equal in the original order.
        if (cmp == 0) {
            cmp = (aa->index > bb->index) - (aa->index < bb->index);
        }
        return cmp;
    }
    
    void sort(struct item a[], int n) {
        qsort(a, n, sizeof(*a), compare_ratios);
    
        for (int i = 0; i < n; i++) {
            a[i].index = i + 1;
        }
        
        printf("Sorted items: \n");
        for (int i = 0; i < n; i++) {
            printf("%d\t%f\t%f\t%f\n", a[i].index, a[i].pw_ratio,
                   a[i].profit, a[i].weight);
        }
    }