我有两个双精度值,但小数位数不同。
123.400 // three decimal places
567.80 // two decimal places
我尝试使用DecimalFormat将Double值转换为String
val stringFormat = DecimalFormat("#,###.000")
println(stringFormat.format(123.400))
println(stringFormat.format(567.80))
val stringFormatZeroAbsent = DecimalFormat("#,###.###")
println(stringFormatZeroAbsent.format(123.400))
println(stringFormatZeroAbsent.format(567.80))
由于“0”表示数字,“#”表示数字,零表示不存在,因此输出为:
123.400
567.800
123.4
567.8
我想要的实际结果是:
123.400
567.80
那个零号没有缺席。
3条答案
按热度按时间nhn9ugyo1#
您可以在这里简单地使用
String.format(String, Double)
,并通过pattern固定三个小数位:这将输出
j2datikz2#
就像人们在评论中所说的那样,
Double
实际上并不 * 存储 * 特定数量的尾随零-- 1.230000000000 和 1.23 是以同样的方式存储的。即使你指定了特定数量的零,这些信息也会丢失。如果你需要存储那些带有任意数量的尾随零的数字,你可能应该把它们存储为
String
s --这样当你打印它们的时候,它们就会正确地显示出来。另一个选择是创建一个类来处理这些额外的数据。
在这里您公开了一个
value
属性,而不是让调用方一直调用toDouble
。或者你可以做些更安全的事
通过使用私有构造函数,你可以保证只创建
TrailingDouble
的有效示例。这意味着你不能真正使用一个 * 数据类 *(你可以用生成的copy
函数绕过私有构造函数),所以你必须编写自己的equals
和hashCode
函数。如果愿意,您可以对实际的
Double
执行相同的方法,指定所需的尾随零的数量:基本上,您可以传入double(不需要验证)和所需的尾随零的数目,它将生成适当的格式字符串以创建字符串表示。
这一个要简单得多,但它确实要求您知道特定
Double
需要多少个尾随零(同样,该信息不包含在Double
本身中,它是单独的)。v9tzhpje3#
我有两个双精度值,但小数位数不同。
双精度浮点数不能存储这些信息。事实上,它们甚至不能存储小数。毕竟计算机是二进制的。这里有一个秘密:
那一行,完全是个谎言,它没有在
d
中存储0.1,那是因为不可能存储这个数。在那之前让你去:什么......那个?想想看:我把1除以3,然后让你们把它写在一张纸上,你从0. 33333333开始,从哪里结束?看到了吗?作为一个使用十进制的人,你不能把这个数字以十进制的格式存储在一张纸上。
计算机不做十进制,他们做二进制。他们可以完美地存储
0.5
。0.25
也没有问题。但是0.1
?不,不行。十分之一在十进制中很好,但是在二进制中就不行了(很明显,除了2的因子,没有什么是这样的)。所以,在十进制中,你可以在一张纸上完美地写上“1/10”,但是你不可能在一张纸上完美地写“1 3”,计算机只能完美地写X Y,其中Y是2的因子。1 65536 -没问题。1 10?不。那么为什么上面的代码会编译呢?因为double/float数学运算会舍入到最接近的可表示数,而且每个数学运算都是类似的舍入。所有的舍入,无论何时何地,都是无声的,没有办法知道这种舍入会带来多少错误。
让我们来看看它的实际效果吧!
因此,当在“我想要x个数字”的意义上谈论“格式化”一个double时,这是完全误导的,因为该变量中的内容是以二进制而不是十进制写出来的数字,并且被舍入到甚至在十进制中也没有意义的东西。
简单的结果是所有的double都有轻微的错误,如果您编写的系统或应用程序中这种轻微的错误是不可接受的(例如:一切财务-你不想失去一个随机美分,由于不可能预测舍入误差!!),那么你不能使用
double
。此问题有两种广泛的解决方案:
1.使用原子,以
int
或long
表示。例如,不要将一个价值1.5美元的商品存储为
double price = 1.50
,而要将其存储为int price = 150;
--换句话说,要找到原子(最小的难以/不可能分割的单位)对于任何它是你试图完美地存储和存储 * 那个 *.考虑到有这样一个原子,当要求你分割时,你无论如何都会被冲洗,你需要考虑一下,没有一个固定的方法来做。例如,如果我是一家银行,我需要收取100欧元的交易费用,-3个公司的合伙企业是平等的伙伴,那么我该怎么做?收取每个€ 33,34?收取每个€ 33,33和吃的美分?掷骰子,随机收取一个伙伴€ 33,34,和其他两个€33,33?要求当事人指定一个主账户,由该账户收取全部费用,如果没有,则收取33.34欧元?在每个账户中跟踪0.3333333333333333333333美分的剩余费用(把余数作为舍入误差扔掉,真的没有人会关心),即使一般在金融系统中,你不能传达分数分的概念吗这个问题没有正确或错误的答案,这意味着
a / b
在这里不可能工作-它怎么知道你想要的是这5个不同的东西中的哪一个?1.使用
java.math.BigDecimal
类,它以decimal的形式存储,并且可以完美地存储。但是请注意,如果您要求BigDecimal将1除以3,它会抛出异常,因为这是不可能的,所以要小心。