我正在执行以下编程练习:Counting power sets。该语句是:
在此kata中,您必须创建一个函数powers / Powers,该函数需要一个数组,并返回可以从中创建的子集数清单。换句话说,计算功率集。
例如
powers([1,2,3])=> 8
...由于...
powers([1,2,3])=> [[],1,[2],[3],[1,2],[2,3],[1,3],[1,2,3]]
您的函数应该能够计算最大为500个的设置,因此小心;那里有很大的数字!
为了进行比较,我的Haskell解决方案可以计算出不到一秒的长度为90 000的数组,所以要快!
为此,您应将传递的每个数组视为一组唯一值kata。
示例:
Powers.powers(new int [] {}); // 1 Powers.powers(new int [] {1});// 2 Powers.powers(new int [] {1,2}); // 4 Powers.powers(新int [] {1,2,3,4}); // 16
我写了以下答案:
import java.math.BigInteger;
import java.util.*;
public class Powers {
public static BigInteger powers/*🔋*/(int[] list) {
System.out.println("list: "+Arrays.toString(list));
System.out.println("list length: "+list.length);
double pow = Math.pow(2, list.length);
System.out.println("pow: "+pow);
return new BigInteger(String.valueOf((long)pow));
}
}
但是,对于100个数组,它不会输出预期的结果。例如,对于以下数组:
list: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
list length: 100
它输出:
9223372036854775807
而不是:
1267650600228229401496703205376
我认为困难是由于将pow结果从double拖到long所产生的,因为它会输出:
pow: 1.2676506002282294E30
然后,我尝试使用modPow来获得更大数字的结果:
import java.math.*;
import java.util.*;
public class Powers {
public static BigInteger powers/*🔋*/(int[] list) {
System.out.println("list: "+Arrays.toString(list));
System.out.println("list length: "+list.length);
BigInteger pow = BigInteger.valueOf(2).modPow(BigInteger.valueOf(list.length), BigInteger.valueOf(Long.MAX_VALUE));
System.out.println("pow: "+pow);
return new BigInteger(String.valueOf(pow));
}
}
但是,当我们使用100长度的数组进行测试时,输出为:
137438953472
何时应该:
1267650600228229401496703205376
我认为挑战是由于Long.MAX_VALUE等于modPow计算的最大值,因为它输出:
pow: 137438953472
此后,我试图在modPow函数中为模数写一个更大的数字,然后我写了这个:
import java.math.*;
import java.util.*;
public class Powers {
public static BigInteger powers/*🔋*/(int[] list) {
System.out.println("list: "+Arrays.toString(list));
System.out.println("list length: "+list.length);
BigInteger modulus = BigDecimal.valueOf(Double.POSITIVE_INFINITY).toBigInteger();
BigInteger pow = BigInteger.valueOf(2).modPow(BigInteger.valueOf(list.length), modulus);
System.out.println("pow: "+pow);
return new BigInteger(String.valueOf(pow));
}
}
但是会引发以下异常:
java.lang.NumberFormatException: Character I is neither a decimal digit number, decimal point, nor "e" notation exponential mark.
at java.base/java.math.BigDecimal.<init>(BigDecimal.java:518)
at java.base/java.math.BigDecimal.<init>(BigDecimal.java:401)
at java.base/java.math.BigDecimal.<init>(BigDecimal.java:834)
at java.base/java.math.BigDecimal.valueOf(BigDecimal.java:1304)
at Powers.powers(Powers.java:7)
我认为它是由Double.POSITIVE_INFINITY生成的,因此给我们提供的数字比BigInteger代表的最大数字大。
因此,前两个代码可以通过以下测试:
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.junit.Ignore;
import java.math.BigInteger;
public class PowersTest {
@Test
public void testPactical() {
assertEquals("An empty array should return 1!", Powers.powers(new int[]{}), BigInteger.valueOf(1));
assertEquals(Powers.powers(new int[]{1}), BigInteger.valueOf(2));
assertEquals(Powers.powers(new int[]{1,2,3,4,5}), BigInteger.valueOf(32));
}
}
但是,两个代码都难以通过100长度数组测试。
另外我读过:
您能帮我找出如何计算Java中非常大的数组的幂集吗?‽
编辑:
通过写解决:
import java.math.*;
import java.util.*;
public class Powers {
public static BigInteger powers/*🔋*/(int[] list) {
return BigInteger.valueOf(2).pow(list.length);
}
}
嗯...我检查了,我认为这可行:
public static BigInteger powers(int[] list) {
return BigInteger.valueOf(2).pow(list.length);
}