Java 和 CPP 的不同输出

时间:2021-07-25 12:30:29

标签: java c++ algorithm binary-search

我正在解决 Nth root of M 问题,我用 Java 解决了,这里是解决方案:

    public int NthRoot(int n, int m)
    {
        // code here
        int ans = -1;
        if (m == 0)
            return ans;
        if (n == 1 || n == 0)
            return m;
        if (m == 1)
            return 1;
        int low = 1;
        int high = m;
        while (low < high) {
            
            int mid = (low + high) / 2;
            int pow = (int)Math.pow(mid, n);
            if (pow == m) {
                
                ans = mid;
                break;
            }
            if (pow > m) {
                
                high = mid;
            } else {
                
                low = mid + 1;
            }
        }
        
        return ans;
    }

它通过了所有的测试用例。但是,当我使用 C++ 解决它时,一些测试用例没有通过。这是 C++ 解决方案:

    int NthRoot(int n, int m)
    {
        // Code here.
        int ans = -1;
        if (m == 0)
            return ans;
        if (n == 1 || n == 0)
            return m;
        if (m == 1)
            return 1;
        int low = 1;
        int high = m;
        while (low < high) {
            
            int mid = (low + high) / 2;
            int po = (int)pow(mid, n);
            if (po == m) {
                
                ans = (int)mid;
                break;
            }
            if (po > m) {
                
                high = mid;
            } else {
                
                low = mid + 1;
            }
        }
        
        return ans;
    } 

它没有通过的测试用例之一是:

6 4096
Java's output is 4 (Expected result)
C++'s output is -1 (Incorrect result)

当我用纸和笔追踪它时,我得到了一个与 Java 相同的解决方案。

但是,当我在 C++ 代码中使用 long long int 时,它工作得很好——但是 Int/int 在 Java 和 C++ 中的大小是一样的,对吧? (当我在 C++ 和 Java 中打印 INT_MAXInteger.MAX_VALUE 时,它输出相同的值。)

1 个答案:

答案 0 :(得分:1)

您可能已经猜到,问题是由于尝试将 double 值转换为 int 值,当该源大于 {{1} }.更具体地说,它涉及 Java 和 C++ 如何处理 int 循环开始附近的强制转换:while

对于您的示例输入 (int po = (int)pow(mid, n);),6 4096 函数在第一次运行该循环时返回的值是 pow,对于 {{1} } 价值。在 Java 中,当您尝试将过大的值转换为整数时,结果是整数类型可表示的最大值,如 this answer 中指定的(我的粗体):

<块引用>
  • 该值必须太大(大的正值或正无穷大),并且第一步的结果是最大的 int 或 long 类型的可表示值

然而,在C++中,当源值超过7.3787e+19时,行为是未定义的(根据这个C++11 Draft Standard):

<块引用>

7.10 浮动积分转换 [conv.fpint]

1 浮点的纯右值 type 可以转换为整数类型的纯右值。转换 截断;也就是说,小数部分被丢弃。行为是 如果截断的值不能在 目的地类型。

然而,虽然形式上未定义,但许多/大多数编译器/平台会在发生这种情况时应用“翻转”,从而导致结果的值非常大(通常为 int) .这就是 Visual Studio 中的 MSVC 所做的,赋予 INT_MAX 值,从而导致 INT_MIN 块运行……并保持运行,直到 -2147483648 循环到达它的终止条件——此时 else 将永远不会被分配任何值,除了初始 while

通过检查 ans 调用返回的 -1 并将 double 设置为 pow(如果合适)以模拟 Java 行为,您可以轻松解决问题:< /p>

po