Number 或 BigInteger 和 BigDecimal 中的错误(或者在这些的 API 文档中)?
根据 Number.longValue()
的规范,该方法应该...
以长整型形式返回指定数字的值。这可能涉及舍入或截断。
但是,BigInteger
(和 BigDecimal
)会重写此方法并返回其整数部分的 64 个低位。代表。例如,来自 BigInteger 的文档:
[...]如果此 BigInteger 太大而无法放入 long 中,则仅返回低位 64 位。[...]
我声称“这可能涉及舍入或截断。”没有说明该方法实际应该返回什么,或者实现或文档中存在错误。
你同意吗,还是我的推理有错误?
示例代码:
import java.math.BigInteger;
import static java.math.BigInteger.*;
public class Main {
public static void main(String[] args) {
BigInteger i = valueOf(Long.MAX_VALUE);
// Result: Long.MAX_VALUE, just as expected.
Number n1 = i;
System.out.println(n1 + " -> " + n1.longValue());
// I expect to get the "rounded" value Long.MAX_VALUE
Number n2 = i.add(ONE);
System.out.println(n2 + " -> " + n2.longValue());
// I expect to get the "rounded" value Long.MAX_VALUE
Number n3 = i.multiply(TEN);
System.out.println(n3 + " -> " + n3.longValue());
}
}
输出:
9223372036854775807 -> 9223372036854775807
9223372036854775808 -> -9223372036854775808
92233720368547758070 -> -10
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
BigInteger.longValue()
的文档继续如下:这重新定义(或澄清)了 Number.longValue() 定义的行为。这很好,尽管有时会产生误导。例如,
java.util.Set
重新定义了add
方法的行为(通过限制重复项)。如果您传递一个Collection
,您可能期望它保存任何值,但具体实现已经重新定义了此行为。更新:我检查了
Long.valueOf(Long.MAX_VALUE).intValue()
的行为方式。它打印-1。所以我认为对于浮点数来说,“舍入或截断”只是一种可能性。否则,Number
类将转换方式完全留给实现者。所以是的 - 它没有透露任何信息。我不会说这有那么糟糕,但它肯定具有误导性。The documentation of
BigInteger.longValue()
continues with:This redefines (or clarifies) the behaviour defined by
Number.longValue()
. This is fine, although it is sometimes misleading. For examplejava.util.Set
redefines the behaviour of theadd
method (by constraining duplicates). If you pass aCollection
you may expect it to hold any values, but the concrete implementation has redefined this behaviour.Update: I checked how does
Long.valueOf(Long.MAX_VALUE).intValue()
behaves. And it prints -1. So I'd assume that by "round or truncate" is just a possibility, regarding floating point numbers. Otherwise theNumber
class leaves the way of conversion entirely to implementors. So yes - it does not tell anything about it. I wouldn't say it is that bad, but it is certainly misleading.我没有看到你的问题,这与你尝试表示特定数字类型范围之外的数字时得到的垃圾有什么不同?
prints
您是否希望 API 告诉您,如果您传递无效输入,您将获得无效输出?
I don't see your question, how is this any different from the garbage you get whenever you try and represent a number outside the bounds of a particular numeric type?
prints
Do you want the API to tell you that you'll get invalid output if you pass invalid input?
“这可能涉及舍入或截断”这一措辞出现在
longValue()
、shortValue()
、charValue( )
和 byteValue() “nofollow noreferrer">Number
,因此很明显,“截断”旨在包括丢失重要的高阶位在某些情况下。问题实际上在于术语“截断”通常意味着低阶位的丢失。 (这就是我在 30 年前的数值分析课程中所记得的。维基百科也同意。 )
相比之下,JLS 5.1.3< /a> 描述了相同的过程(当缩小整型原始类型时),如下所示:
所以,是的,我同意 javadoc 是不正确的。提交错误报告。
注意
我最初删除了这个,因为我认为我提交错误报告的建议可能是徒劳的(基于我过去处理文档错误报告的经验)。但是@aioobe已经提交了一份错误报告...(错误ID:7000825)
The wording "This may involve rounding or truncation" appears in the javadocs for the
longValue()
,shortValue()
,charValue()
andbyteValue()
ofNumber
, so it is clear that "truncation" is intended to include loss of significant high order bits in some cases.The problem really is that the term "truncation" conventionally means loss of lower order bits. (That's how I remember it from my numerical analysis course, 30 years ago. And Wikipedia agrees.)
By contrast, the JLS 5.1.3 describes the same process (when narrowing integral primitive types) as follows:
So yes, I agree that the javadoc is incorrect. Submit a bug report.
NOTE
I had originally deleted this because I thought my suggestion to submit a bug report was probably futile (based on my past experience with documentation bug reports). But @aioobe has submitted a bug report ... (Bug ID: 7000825)