如何解决Java 和 CPP 的不同输出
我正在解决 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_MAX
和 Integer.MAX_VALUE
时,它输出相同的值。)
解决方法
您可能已经猜到,问题是由于尝试将 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 行为,您可以轻松解决问题:
po
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。