英文:
Java Datatypes - Hacker Rank
问题
我正在尝试解决 HackerRank 上的一个问题,我需要做的是在这里列出的 [链接][1](代码的解释),我已经设法使代码运行并且能够工作,但是有两个测试未通过。[![在这里输入图片描述][2]][2]
这是我的代码:
```java
import java.util.Scanner;
public class JavaDatatypes {
public static void main(String[] argh) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
for (int i = 0; i < t; i++) {
try {
long x = sc.nextLong();
System.out.println(x + " 可以容纳于:");
int[] bits = {8, 16, 32, 64};
String[] strings = {"byte", "short", "int", "long"};
for (int j = 0; j < bits.length; j++) {
long range = (long) (Math.pow(2, bits[j] - 1));
if (x >= -range && x <= range - 1) {
System.out.println("* " + strings[j]);
}
}
// 完成代码
} catch (Exception e) {
System.out.println(sc.next() + " 无法放入任何数据类型中。");
}
}
}
}
我查看了预期的输出,它期望将 9223372036854775807
作为一个 long 输出,但是我的代码没有将其作为 long 输出,我不确定原因。
<details>
<summary>英文:</summary>
I am trying to solve a problem on hacker rank so what I have to do is listed [here][1] (explanation of the code), and I have managed to make the code run and work, but it fails 2 of the tests.[![enter image description here][2]][2]
here is my code.
import java.util.Scanner;
public class JavaDatatypes {
public static void main(String[] argh) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
for (int i = 0; i < t; i++) {
try {
long x = sc.nextLong();
System.out.println(x + " can be fitted in:");
int[] bits = {8, 16, 32, 64};
String[] strings = {"byte", "short", "int", "long"};
for (int j = 0; j < bits.length; j++) {
long range = (long) (Math.pow(2, bits[j] - 1));
if (x >= -range && x <= range -1) {
System.out.println("* " + strings[j]);
}
}
//Complete the code
} catch (Exception e) {
System.out.println(sc.next() + " can't be fitted anywhere.");
}
}
}
}
I have looked at the expected output and it expects `9223372036854775807` to be outputed as a long, and my code isn't outputting that as a long I am not sure why.
[1]: http://hackerrank.com/challenges/java-datatypes/problem
[2]: https://i.stack.imgur.com/aSGcZ.png
</details>
# 答案1
**得分**: 1
问题在于你的代码中使用了 `double pow(double a, double b)`。当结果接近 `Long.MAX_VALUE` 时,结果会被**舍入**。你可以通过使用 `BigInteger` 进行验证:
```java
String str1 = BigInteger.valueOf(2).pow(bits[j] - 1).toString();
String str2 = String.valueOf((long)Math.pow(2, bits[j] - 1));
这些字符串应该每次都相等,但对于 2^16
,它们并不相等。这就是为什么对于 2^16
,你的 x <= range - 1
不正确。
你不需要使用 for loop
来进行检查。Java 有像 Byte.MIN_VALUE
、Byte.MAX_VALUE
这样的常量。
public static void main(String[] argh) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
for (int i = 0; i < t; i++) {
try {
long x = sc.nextLong();
System.out.println(x + " 可以放在以下类型中:");
if (x >= Byte.MIN_VALUE && x <= Byte.MAX_VALUE)
System.out.println("* byte");
if (x >= Short.MIN_VALUE && x <= Short.MAX_VALUE)
System.out.println("* short");
if (x >= Integer.MIN_VALUE && x <= Integer.MAX_VALUE)
System.out.println("* int");
System.out.println("* long");
} catch(Exception e) {
System.out.println(sc.next() + " 无法放在任何类型中。");
}
}
}
英文:
Problem in you code is that you use double pow(double a, double b)
. When you have result closer to Long.MAX_VALUE
- the result is rounded. You can check it by BitInteger
:
String str1 = BigInteger.valueOf(2).pow(bits[j] - 1).toString();
String str2 = String.valueOf((long)Math.pow(2, bits[j] - 1));
These strings should be equal every time, but for 2^16
- it's not. That's why for 2^16
your x <= range - 1
is not correct.
You do not need to use for loop
to check this. Java has constants like Byte.MIN_VALUE
, Byte.MAX_VALUE
.
public static void main(String[] argh) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
for (int i = 0; i < t; i++) {
try {
long x = sc.nextLong();
System.out.println(x + " can be fitted in:");
if (x >= Byte.MIN_VALUE && x <= Byte.MAX_VALUE)
System.out.println("* byte");
if (x >= Short.MIN_VALUE && x <= Short.MAX_VALUE)
System.out.println("* short");
if (x >= Integer.MIN_VALUE && x <= Integer.MAX_VALUE)
System.out.println("* int");
System.out.println("* long");
} catch(Exception e) {
System.out.println(sc.next() + " can't be fitted anywhere.");
}
}
}
答案2
得分: 1
只需省略对64位和long
的检查。
如果long x = sc.nextLong();
成功执行而没有异常,你已经知道这个数字适用于long
类型。所以,如果没有异常,你可以始终打印“* long”。
关于使用Math.pow()
的一个注意事项:它基于浮点算术,因此可能涉及小的舍入误差。2的幂可以通过位移运算来计算,因此
long range = (long) (Math.pow(2, bits[j] - 1))
可以替换为
long range = 2L << (bits[j] - 1)
这可以得到精确的结果,而且比使用Math.pow()
更快。
英文:
Just omit the check for 64 bits and long
.
If long x = sc.nextLong();
succeeds without exception, you already know that the number fits into the long
type. So, you can always print "* long" if you didn't get an exception.
One remark on using Math.pow()
: it's based on floating-point arithmetic and as such, it might involve small rounding errors. Powers of 2 can be computed by bit-shifting, so
long range = (long) (Math.pow(2, bits[j] - 1))
can be replaced by
long range = 2L << (bits[j] - 1)
This gives exact results and also is faster than Math.pow()
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论