使用乘法方法交换数字在 C 中不起作用

发布于 2025-01-19 20:16:03 字数 765 浏览 0 评论 0 原文

最近,我一直在C中进行编码,我试图解决一个数字交换问题。通过使用临时变量,我以更轻松的方式做到了这一点。但是我的教练告诉我使用另一种没有温度变量的方法。这是我的代码:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int a,b,temp;
    printf("Enter two numbers: ");
    scanf("%d%d",&a,&b);
    printf("Entered Numbers:%d,%d \n",a,b);
    temp = a;   //This method is the easiest one.
    a = b;
    b = temp;
    printf("Numbers are swapped as: %d,%d \n",a,temp);
    a = (a*b)/a;
    b = (a*b)/b;
    printf("Numbers are swapped as: %d,%d",a,b);
    return EXIT_SUCCESS;
}

我得到的输出如下:

Enter two numbers: 50 32
Entered Numbers:50,32 
Numbers swapped with temp are: 32,50 
Numbers swapped without temp are: 50,50

有人可以猜出可能的错误吗?我相信我的数学是对的,但是为什么这样显示呢?

Recently I have been coding in C and I was trying to solve a number swapping problem. I have done it the easier way, by using a temporary variable. But my instructor told me use another method without temp variable. This is my code:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int a,b,temp;
    printf("Enter two numbers: ");
    scanf("%d%d",&a,&b);
    printf("Entered Numbers:%d,%d \n",a,b);
    temp = a;   //This method is the easiest one.
    a = b;
    b = temp;
    printf("Numbers are swapped as: %d,%d \n",a,temp);
    a = (a*b)/a;
    b = (a*b)/b;
    printf("Numbers are swapped as: %d,%d",a,b);
    return EXIT_SUCCESS;
}

I got the output as follows:

Enter two numbers: 50 32
Entered Numbers:50,32 
Numbers swapped with temp are: 32,50 
Numbers swapped without temp are: 50,50

Can anyone guess what might be the error? I believe my math is right, but why is it showing like this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

通知家属抬走 2025-01-26 20:16:03

您在第二个逻辑中犯了一个愚蠢的错误,只需替换为提到的一个即可:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int a,b,temp;
    printf("Enter two numbers: ");
    scanf("%d%d",&a,&b);
    printf("Entered Numbers:%d,%d \n",a,b);
    temp = a;   //This method is the easiest one.
    a = b;
    b = temp;
    printf("Numbers are swapped as: %d,%d \n",a,temp);
    a = a * b; //Change 1  
    b = a / b; //Change 2 
    a = a / b; //Change 3
    printf("Numbers are swapped as: %d,%d",a,b);
    return EXIT_SUCCESS;
}

You have made a silly mistake in your second logic, just replace with mentioned one:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int a,b,temp;
    printf("Enter two numbers: ");
    scanf("%d%d",&a,&b);
    printf("Entered Numbers:%d,%d \n",a,b);
    temp = a;   //This method is the easiest one.
    a = b;
    b = temp;
    printf("Numbers are swapped as: %d,%d \n",a,temp);
    a = a * b; //Change 1  
    b = a / b; //Change 2 
    a = a / b; //Change 3
    printf("Numbers are swapped as: %d,%d",a,b);
    return EXIT_SUCCESS;
}
Hello爱情风 2025-01-26 20:16:03

您在交换代码中犯了一个错误:乘法方法使用3个步骤:

  • 将产品 a * b 计算到 a a
  • divide a a by b 中的 b ,有效地将 b 设置为 a 的原始值。
  • Divide a b 纳入 a ,有效地将产品除以 a 的原始值,因此设置 a b 的原始值。

这种方法的问题在于,它在许多情况下不起作用:

  • 如果 b 为零,则第一部门的行为不确定,在许多情况下,
  • 如果 a 为零,则 在许多情况下崩溃了。 ,第二个部门的行为不确定。
  • 如果 a * b 超过类型 int 的范围,则您的行为也不确定,产生不正确的结果甚至崩溃(尝试交换 65536 65536 )。

还有另一种没有临时变量的方法更安全和可靠:您可以XOR数字并再次使用XOR来检索原始值并交换它们,而不是乘以数字并分配产品。

还请注意,您的第三个 printf 语句不正确:您打印 temp 而不是 b 的值。

这是一个修改后的版本:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int a, b, temp;
    printf("Enter two numbers: ");
    if (scanf("%d%d", &a, &b) != 2)
        return EXIT_FAILURE;
    printf("Entered Numbers: %d,%d\n", a, b);
    temp = a;   //This method is the easiest one.
    a = b;
    b = temp;
    printf("Numbers are swapped with temp as: %d,%d\n", a, b);
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    printf("Numbers are swapped with xor as: %d,%d\n", a, b);
    a = a * b;
    b = a / b;
    a = a / b;
    printf("Numbers are swapped with multiplication as: %d,%d\n", a, b);
    return EXIT_SUCCESS;
}

示例运行而无需优化:

Enter two numbers: 12 42
Entered Numbers: 12,42
Numbers are swapped with temp as: 42,12
Numbers are swapped with xor as: 12,42
Numbers are swapped with multiplication as: 42,12
Enter two numbers: 1 0
Entered Numbers: 1,0
Numbers are swapped with temp as: 0,1
Numbers are swapped with xor as: 1,0
Floating point exception: 8
Enter two numbers: 65536 65536
Entered Numbers: 65536,65536
Numbers are swapped with temp as: 65536,65536
Numbers are swapped with xor as: 65536,65536
Floating point exception: 8

相同的运行效果( clang gcc ):

Enter two numbers: 12 42
Entered Numbers: 12,42
Numbers are swapped with temp as: 42,12
Numbers are swapped with xor as: 12,42
Numbers are swapped with multiplication as: 42,12
Enter two numbers: 1 0
Entered Numbers: 1,0
Numbers are swapped with temp as: 0,1
Numbers are swapped with xor as: 1,0
Numbers are swapped with multiplication as: 0,1
Enter two numbers: 65536 65536
Entered Numbers: 65536,65536
Numbers are swapped with temp as: 65536,65536
Numbers are swapped with xor as: 65536,65536
Numbers are swapped with multiplication as: 65536,65536

发生了什么?编译器打破了吗?可以用 goldbolt的编译器资源管理器强>和 GCC 能够识别3种交换方法,并使用4 MOV 指令生成相同的交换代码。由于第三种方法在乘法或划分失败的情况下具有未定义的行为,因此可以产生任何结果,包括预期的结果。一个公然的行为滥用案件。您的讲师应该对这一发现感到惊讶。

You made a mistake in the swapping code: the multiplication method uses 3 steps:

  • compute the product a * b into a
  • divide a by b into b, effectively setting b to the original value of a.
  • divide a by b into a, effectively dividing the product by the original value of a, hence setting a to the original value of b.

The problem with this approach is it does not work for many cases:

  • if b is zero, the first division has undefined behavior, crashing the program in many cases
  • if a is zero, the second division has undefined behavior.
  • if a * b exceeds the range of type int, you also have undefined behavior, producing incorrect results or even a crash (try swapping 65536 and 65536).

There is another method without a temporary variable the is much safer and reliable: instead of multiplying the numbers and dividing the product, you can xor the numbers and use xor again to retrieve the original values and swap them.

Note also that your third printf statement is incorrect: you print the value of temp instead of b.

Here is a modified version:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int a, b, temp;
    printf("Enter two numbers: ");
    if (scanf("%d%d", &a, &b) != 2)
        return EXIT_FAILURE;
    printf("Entered Numbers: %d,%d\n", a, b);
    temp = a;   //This method is the easiest one.
    a = b;
    b = temp;
    printf("Numbers are swapped with temp as: %d,%d\n", a, b);
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    printf("Numbers are swapped with xor as: %d,%d\n", a, b);
    a = a * b;
    b = a / b;
    a = a / b;
    printf("Numbers are swapped with multiplication as: %d,%d\n", a, b);
    return EXIT_SUCCESS;
}

Sample runs without optimisations:

Enter two numbers: 12 42
Entered Numbers: 12,42
Numbers are swapped with temp as: 42,12
Numbers are swapped with xor as: 12,42
Numbers are swapped with multiplication as: 42,12
Enter two numbers: 1 0
Entered Numbers: 1,0
Numbers are swapped with temp as: 0,1
Numbers are swapped with xor as: 1,0
Floating point exception: 8
Enter two numbers: 65536 65536
Entered Numbers: 65536,65536
Numbers are swapped with temp as: 65536,65536
Numbers are swapped with xor as: 65536,65536
Floating point exception: 8

The same runs with optimisations (clang or gcc):

Enter two numbers: 12 42
Entered Numbers: 12,42
Numbers are swapped with temp as: 42,12
Numbers are swapped with xor as: 12,42
Numbers are swapped with multiplication as: 42,12
Enter two numbers: 1 0
Entered Numbers: 1,0
Numbers are swapped with temp as: 0,1
Numbers are swapped with xor as: 1,0
Numbers are swapped with multiplication as: 0,1
Enter two numbers: 65536 65536
Entered Numbers: 65536,65536
Numbers are swapped with temp as: 65536,65536
Numbers are swapped with xor as: 65536,65536
Numbers are swapped with multiplication as: 65536,65536

What is going on? Is the compiler broken? As can be verified with Goldbolt's Compiler Explorer, when optimisations are turned on, both clang and gcc are able to identify the 3 swapping methods and generate the same swapping code with 4 mov instructions. Since the third method has undefined behavior on cases where the multiplication or division would fail, producing any result is OK, including the expected one. A blatant case of undefined behavior abuse. Your instructor should be amazed at this discovery.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文