将双精度浮点数转换为整型数组

28

我有一个双精度数

double pi = 3.1415;

我想将这个转换为整数数组

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'; 
它正在工作,但我不喜欢这种解决方案,因为我认为很多数据类型之间的转换可能会导致错误。我的代码是否完整,还是需要检查其他内容?您会如何处理这个问题?

你可能会对二进制数字感兴趣,它们可以用0和1的数组表示double类型。Double类有bits的转换方法。在你的例子中,数组中可能包含10的负四次方。但是Doubles本身也存在问题,因为toString()方法可能会返回"3.14149999998"这样的值。 - Joop Eggen
考虑写一个Java 7的答案,但似乎没有意义。我只会做两个改变:使用piString.toCharArray进行foreach循环和使用Character::getNumericValue方法。编辑:对于整数数组仍然需要索引... - JollyJoker
如果数字很大会发生什么?我的意思是:如果一个数字的字符串表示是1E200,你想让数组变成{1,2,0,0}还是{1,0,0,0,0,...,0},有200个零? - Giacomo Alzetta
如果我们了解你为什么这样做,可能会给出更有意义的答案。你将如何处理生成的数组? - David Dubois
不好意思,但真正的问题应该是“将双精度转换为十进制整数数组而不进行字符串转换”。 - pdem
显示剩余2条评论
6个回答

23

我不知道直接的方法,但我认为这种方法更简单:

int[] piArray = String.valueOf(pi)
                      .replaceAll("\\D", "")
                      .chars()
                      .map(Character::getNumericValue)
                      .toArray();

1
想到了相同的解决方案,只是你比我早一点 :) - Glains
12
我使用了replaceAll("\\D", "")这段代码来过滤掉非数字的字符。 - Glains
@RahimDastar 因为 double 只有一个 ., 所以请使用 replaceFirst 而不是 replaceAll, 否则会出现 1+ 的问题。 - Eugene
2
@Eugene 如果 double 是 1.13E+21,replaceFirst 方法无法正常工作。 - Rahim Dastar
2
BigDecimal.valueOf(pi).toPlainString()可以完全避免指数形式。 - Radiodef
显示剩余3条评论

13

既然你想避免强制类型转换,那么这是一种算术方式,假设你只需要处理正数:

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)来轻松完成。

请注意,由于浮点算术运算,在不能用二进制完全表示的值上,它将给出您可能不希望看到的结果。

这里是一个ideone,其中说明了问题,并且您可以尝试我的代码。


2
我简直不敢相信这是唯一提到浮点数表示的答案。+1 - Konrad Rudolph
虽然算术方法很好,但是由于不精确的浮点数表示问题,这对于实际数字来说几乎没有用处。当“3.1415”产生一个带有52个值(3、1、4、1、5、一堆零,然后是无用的垃圾“精度”)的列表时,你违反了用户的期望。 - ShadowRanger
1
@ShadowRanger 是的,绝对同意。当我测试我的解决方案时,“记得”浮点精度问题,并认为我的答案仍然会引起兴趣(特别是如果这是作业,那么我不会感到惊讶,如果这个问题是老师想让他的学生遇到的)。通过使用“BigDecimal”,仍然可以实现真实世界的算术解决方案,但我不确定它是否比基于字符串的解决方案具有更多优势。 - Aaron
1
@Aaron:是的。如果值以double形式到达,则在转换为BigDecimal时会遇到相同的问题; BigDecimaldouble构造函数保留了二进制浮点值的精确十进制表示,因此BigDecimal有用的唯一方法是如果您可以将输入类型更改为BigDecimal(将问题推给调用者),或通过字符串转换执行隐式舍入(这只是隐藏了它基本上都是基于字符串解析的事实)。你的答案并没有错(不会被踩),但它可能除了演示之外没有什么用处。 - ShadowRanger
@ShadowRanger 字符串解决方案从根本上存在这个问题;由于字符串格式化程序已经提供了一些处理,所以它不太明显,但它仍然存在。在某种程度上,字符串解决方案只是更好地隐藏了潜在的错误,而这通常不是一个好主意。 - Konrad Rudolph
@KonradRudolph: 有点像。如果值是由用户输入的,在现代Python中(不确定Java是否做出了相同的努力),字符串形式始终是最小的(最短的字符串,如果解释为文字,则会产生相同的二进制浮点值)。如果Java和Python匹配行为,则显式输入的“double”将按预期工作。问题将出现在计算的“double”上,其中数字产生不希望的精度(例如0.1 + 0.2 == 0.30000000000000004,而不是0.3)。 - ShadowRanger

4
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();

你能解释一下为什么更安全吗?我很感兴趣。 - Glains

3

你可以在Java 8中使用

int[] piArray = piString.chars().map(Character::getNumericValue).toArray();

0

这也可以工作

int[] piArray = piString.chars().map(c -> c-'0').toArray();

-2

这个解决方案不做任何假设,使用字符串操作来获取您想要的结果。获取双精度数,将其转换为字符串,删除非法字符,然后将剩余的每个字符强制转换为整数并按它们在双精度数中出现的顺序存储在数组中。

        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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接