将 double 转换为 int 数组
Posted
技术标签:
【中文标题】将 double 转换为 int 数组【英文标题】:Convert double to int array 【发布时间】:2019-02-19 01:14:46 【问题描述】:我有双份
double pi = 3.1415;
我想把它转换成一个 int 数组
int[] piArray = 3,1,4,1,5;
我想出了这个
double pi = 3.1415;
String piString = Double.toString(pi).replace(".", "");
int[] piArray = new int[piString.length()];
for (int i = 0; i <= piString.length()-1; i++)
piArray[i] = piString.charAt(i) - '0';
它有效,但我不喜欢这种解决方案,因为我认为数据类型之间的大量转换会导致错误。我的代码是否完整,还是需要检查其他内容?
您将如何解决这个问题?
【问题讨论】:
您可能对以 2 为基数的数字感兴趣,即作为 0 和 1 的数组的双精度数。 Double 类具有 位 的转换。上面你可以在数组中有十的幂:在你的例子中是-4。双打本身就有问题,因为 toString 很可能给出 "3.14149999998" 想过写一个 Java 7 的答案,但这似乎毫无意义。piString.toCharArray
的 foreach 和使用 Character::getNumericValue
是我要做的唯一更改。编辑:仍然需要 int 数组的索引...
如果数字很大怎么办?我的意思是:如果一个数字的字符串表示是1E200
,你希望数组变成1,2,0,0
还是1,0,0,0,0,...,0
,有200 个零?
您对(例如)double d = 0.1
的期望是什么?由于浮点恶作剧,这远非微不足道。此外,您为什么认为数据类型之间的转换会导致错误? — 最后,对于未来,此类问题更适合codereview.stackexchange.com。
如果我们了解您为什么这样做,我们也许可以给出更有意义的答案?您将如何处理生成的数组?
【参考方案1】:
我不知道直接的方法,但我认为它更简单:
int[] piArray = String.valueOf(pi)
.replaceAll("\\D", "")
.chars()
.map(Character::getNumericValue)
.toArray();
【讨论】:
想出了相同的解决方案,你有点早:) 我已经使用replaceAll("\\D", "")
过滤任何非数字。
Glains 发布您的解决方案或编辑,因为我认为这是更强大的解决方案。
@Eugene if double 是 1.13E+21 replaceFirst 不起作用
BigDecimal.valueOf(pi).toPlainString()
完全避免了指数形式。【参考方案2】:
既然你想避免强制转换,这里是算术方法,假设你只需要处理正数:
List<Integer> piList = new ArrayList<>();
double current = pi;
while (current > 0)
int mostSignificantDigit = (int) current;
piList.add(mostSignificantDigit);
current = (current - mostSignificantDigit) * 10;
通过首先检查符号然后使用与current = Math.abs(pi)
相同的代码,可以轻松地处理负数。
请注意,由于浮点运算,它会为您提供无法以二进制完美表示的值的结果。
Here 是一个 ideone,它说明了问题以及您可以在哪里尝试我的代码。
【讨论】:
我不敢相信这是唯一提到浮点表示的答案。 +1 虽然算术方法很好,但浮点表示不精确的问题使得这对现实世界的数字毫无用处。当3.1415
产生一个具有 52 个值的List
(3、1、4、1、5,一堆零,然后相当于无用的垃圾“精度”)时,你就大大违反了用户的期望。
@ShadowRanger 是的,绝对同意。我在测试我的解决方案时“记住”了浮点精度问题,并且认为我的答案仍然会引起人们的兴趣(特别是如果它是家庭作业,在这种情况下,如果这个问题是老师希望他的学生遇到的问题,我不会感到惊讶)。使用BigDecimal
仍然可以实现现实世界的算术解决方案,但我不确定它是否比基于字符串的解决方案有很多优势
@Aaron:是的。如果该值以double
的形式出现,则转换为BigDecimal
时会遇到同样的问题; BigDecimal
的 double
构造函数保留了二进制浮点值的精确十进制表示,因此 BigDecimal
帮助的唯一方法是将输入类型更改为 BigDecimal
(将问题推给调用者) ,或通过字符串转换执行隐式舍入(这只是隐藏了它都是有效地基于字符串解析的事实)。您的答案没有错(不是否决),它可能对演示没有任何用处。
@ShadowRanger 字符串解决方案根本也有这个问题;它不太明显,因为字符串格式化程序已经为它提供了一些处理,但它仍然存在。在某种程度上,字符串解决方案只是更好地隐藏了潜在的错误,这通常不是一个好主意。【参考方案3】:
int[] result = Stream.of(pi)
.map(String::valueOf)
.flatMap(x -> Arrays.stream(x.split("\\.|")))
.filter(x -> !x.isEmpty())
.mapToInt(Integer::valueOf)
.toArray();
或者使用java-9
的更安全的方法:
int[] result = new Scanner(String.valueOf(pi))
.findAll(Pattern.compile("\\d"))
.map(MatchResult::group)
.mapToInt(Integer::valueOf)
.toArray();
【讨论】:
你能解释一下为什么它更安全吗,会对此感兴趣。【参考方案4】:你可以在java 8中使用
int[] piArray = piString.chars().map(Character::getNumericValue).toArray();
【讨论】:
【参考方案5】:这也可以
int[] piArray = piString.chars().map(c -> c-'0').toArray();
【讨论】:
【参考方案6】:此解决方案不做任何假设,并使用字符串操作来获得您想要的结果。获取双精度,将其转换为字符串,删除非法字符,然后将每个剩余字符转换为整数并将它们存储在数组中 - 按照它们在双精度中出现的顺序
double pi = 3.1415;
String temp = ""+ pi;
String str = "";
String validChars = "0123456789";
//this removes all non digit characters
//so '.' and '+' and '-' same as string replace(this withThat)
for(int i =0; i<temp.length(); i++)
if(validChars.indexOf(temp.charAt(i)) > -1 )
str = str +temp.charAt(i);
int[] result = new int[str.length()];
for(int i =0; i<str.length(); i++)
result[i] = Integer.parseInt(""+str.charAt(i));
System.out.print(result[i]);
return result; //your array of ints
【讨论】:
以上是关于将 double 转换为 int 数组的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Swift 将 Int of Array 值转换为 Double [关闭]