【问题标题】:(num % 2) can result in 0, 1, and more? in C# [duplicate](num % 2) 可以导致 0、1 和更多?在 C# [重复]
【发布时间】:2020-01-11 11:06:45
【问题描述】:

我正在解决一些算法测试,它是Collatz conjecture

总之,

1-1. if the number is even, divide it by 2
1-2. if odd, multiply it by 3 and plus 1
2. repeat the same process 1(1-1 or 1-2), until the number become 1.

例如, 6 变为 1,经过 8 次尝试(6 → 3 → 10 → 5 → 16 → 8 → 4 → 2 → 1)。

在测试中,应该以500次尝试结束,并返回尝试次数。 如果失败 500 次,则返回 -1。

这是我的代码。

using System;

public class Program {

    public int Main(int num) {

        int answer = -1;
        int maxTry = 500;
        int count = 0;

        if (num == 1)
            return count;
        for (count = 0; count < maxTry; count++)
        {
            // 1-1
            if (num % 2 == 0)
            {
                num /= 2;
            }
            // 1-2
            else
            {
                num = num * 3 + 1;
            }

            if (num == 1)
            {
                answer = count + 1;
                break;
            }
        }

        Console.Write(answer);
        return answer;
    }
}

在遇到“626331”之前,它运行良好! 在解释中,626331 不可能是 500 次中的 1。 但是使用我的代码,它返回 488,这意味着它在 488 次尝试时变为 1。 当我重复打印过程时,它看起来运行良好。

经过所有尝试,发现分割是问题所在。

我改变了这个

if (num % 2 == 0)
...
else
...

进入

if (num % 2 == 0)
...
else if (num % 2 == 1)
...

现在每个案例都可以完美运行! 但我对这种情况没有任何线索。

这是在线编码测试,编译选项是 C# Mono C# Compiler 5.14.0.177

【问题讨论】:

  • 你的程序溢出了int范围,即-2,147,483,648 to 2,147,483,647。而您的“修复”仅有效,因为现在您可以获得 0、1 或 -1。处理 long 而不是 int 以获得正确的行为。
  • @PeterDeniho 虽然它在某种意义上有点重复,但核心问题不是代码中没有覆盖 mod 负数,而是溢出本身。因此,我认为这不是链接问题的欺骗
  • 在循环过程中,变量num最终得到1069967879的值。将其乘以 3,结果为3209903637,超出了int 类型的范围(2147483647 的最大值)。溢出导致负数-1085063659。添加== 1 子句隐藏了这个事实,但并没有真正解决问题,因为计算仍然没有产生算法预期范围内的数字。有关 C# 中模运算的更多详细信息,请参阅标记的重复项。
  • @Andrei:帖子的标题是 _"(num % 2) 会导致 0、1 和更多?从% 得到一个结果,而不是01。也就是说,我还添加了指向重复帖子的链接,该帖子涉及 int 和 C# 中其他基本类型的值范围。
  • @PeterDuniho,我现在也明白这一点,谢谢。但是,op 没有意识到的核心问题是溢出。可以在这里附上两个骗子吗?

标签: c# algorithm collatz


【解决方案1】:

您正在溢出,一旦溢出,结果将为负数,num % 2 可以返回 0 或 -1。 C# 中的% 运算符是余数运算符,而不是数学模运算符。看 Mod of negative number is melting my brain

您需要使用更宽的整数类型 (long) 并启用 checked mode 来检测溢出

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-23
    • 2017-01-27
    • 1970-01-01
    • 2013-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多