在我的JAVA程序中有这样的代码:
int f_part = (int) ((f_num - num) * 100);
f_num是double,num是long。我只想将小数部分取出并将其分配给f_part。但有时候f_part值比它的值小1。这意味着如果f_num = 123.55和num = 123,但f_part等于54.它只发生f_num而num大于100.我不知道为什么会发生这种情况。请有人解释为什么会发生这种情况并纠正它。
答案 0 :(得分:5)
这是由于双打精度有限。
问题的根源在于文字123.55
实际上代表了值123.54999...
。
如果您打印它可能似乎保持值123.55
:
System.out.println(123.55); // prints 123.55
但事实上,印刷值是近似值。这可以通过创建一个BigDecimal
来显示(它提供任意精度)并打印BigDecimal:
System.out.println(new BigDecimal(123.55)); // prints 123.54999999999999715...
你可以通过Math.round
来解决它但你必须知道源double实际需要多少小数,或者你可以选择通过double的字符串表示实际上经历了相当复杂的算法
如果您正在使用货币,我强烈建议您
BigDecimal
表示,以便您准确地将数字存储为0.1
,或int
存储分数(而不是存储双倍数量的美元)。这两种方式都完全可以接受并在实践中使用。
答案 1 :(得分:3)
在内部,计算机使用不能的格式(二进制浮点) 准确地表示一个像0.1,0.2或0.3的数字。
编译或解释代码时,您的“0.1”已经存在 四舍五入到该格式的最接近的数字,这导致一个小的 甚至在计算发生之前就会出现舍入错误。
看起来你在计算货币价值。 double
是完全不适合的格式。请改用BigDecimal
。
答案 2 :(得分:1)
int f_part = (int) Math.round(((f_num - num) * 100));
答案 3 :(得分:0)
这是最常被问及(和回答)的问题之一。浮点算术不能产生精确的结果,因为在64位内部不可能有实数的无穷大。如果您需要任意精度,请使用BigDecimal。
答案 4 :(得分:0)
浮点运算并不像看起来那么简单,并且可能存在精度问题。 有关详细信息,请参阅Why can't decimal numbers be represented exactly in binary?,What Every Computer Scientist Should Know About Floating-Point Arithmetic。
如果您需要绝对精确,可能需要使用BigDecimal
。