I have some code to figure out the correctness of manipulations on different data types (int, long, double) comparing to BigInteger. The manipulation is getting a factorial of a number until the result is the same as BigInteger has.
The question is how could i change my code, make more generic, compact and clean? How could i get the only one method, not 4 for different types?
The logic in this methods is pretty the same as well as the flow.
The code (without comparing logic) is:
private static HashMap<BigInteger, BigInteger> bigIntegerFactorials = new HashMap<>();
private static BigInteger bigIntegerFactorial(BigInteger number) {
if (number.equals(BigInteger.ONE)) {
return BigInteger.ONE;
}
BigInteger result = bigIntegerFactorials.get(number);
if (result == null) {
result = number.multiply(bigIntegerFactorial(number.subtract(BigInteger.ONE)));
bigIntegerFactorials.put(number, result);
}
return result;
}
private static HashMap<Integer, Integer> intFactorials = new HashMap<>();
private static int intFactorial(int number) {
if (number == 1) {
return 1;
}
Integer result = intFactorials.get(number);
if (result == null) {
result = number * intFactorial(number - 1);
intFactorials.put(number, result);
}
return result;
}
private static HashMap<Long, Long> longFactorials = new HashMap<>();
private static long longFactorial(long number) {
if (number == 1) {
return 1L;
}
Long result = longFactorials.get(number);
if (result == null) {
result = number * longFactorial(number - 1);
longFactorials.put(number, result);
}
return result;
}
private static HashMap<Double, Double> doubleFactorials = new HashMap<>();
private static double doubleFactorial(double number) {
if (number == 1) {
return 1.;
}
Double result = doubleFactorials.get(number);
if (result == null) {
result = number * doubleFactorial(number - 1);
doubleFactorials.put(number, result);
}
return result;
}
Thanks a lot in advance.
You could pass the multiply and decrement functions to a generic method:
private static Map<Number, Number> factorials = new HashMap<> ();
private static <T extends Number> T factorial(T n, BinaryOperator<T> multiply, UnaryOperator<T> decrement) {
if (n.doubleValue() == 1) return n;
T result = (T) factorials.get(n);
if (result == null ){
result = multiply.apply(n, factorial(decrement.apply(n), multiply, decrement));
factorials.put(n, result);
}
return result;
}
Then you can change your primitive methods like so:
public static int intFactorial(int number) {
return factorial(number, (i, j) -> i * j, i -> i - 1);
}
WARNING: this method seems to crash Netbeans but compiles fine with javac...
If you are really trying to compute a factorial, then there isn't any need for double or BigDouble since factorial only applies to integer values. And since that's true, you can convert any integer type to BigInteger and go with a single method that takes any Number returns BigInteger.
Here's a test class
public class Junk {
public static void main(String[] args) {
long val = 9;
Junk j = new Junk();
System.out.println(val + "! = " + j.factorial(val));
BigInteger nine = new BigInteger("9");
System.out.println(nine + "! = " + j.factorial(nine));
short nine_short = 9;
System.out.println(nine_short + "! = " + j.factorial(nine_short));
}
private HashMap<BigInteger, BigInteger> map = new HashMap<>();
public BigInteger factorial(Number number){
if(1 == number.intValue()){
return BigInteger.ONE;
}
BigInteger bigInteger = new BigInteger(number.toString());
BigInteger result = map.get(bigInteger);
if(result == null){
result = bigInteger.multiply(factorial(bigInteger.subtract(BigInteger.ONE)));
map.put(bigInteger,result);
}
return result;
}
}
And the output
9! = 362880
9! = 362880
9! = 362880
Related
Problem Statement: Given a 32-bit signed integer, reverse digits of an integer.
Example 1:
Input: 123
Output: 321
Example 2:
Input: -123
Output: -321
My Solution:
class Solution7{
public int reverse(int x) {
if(x>Integer.MAX_VALUE || x<Integer.MIN_VALUE) {
return 0;
}
StringBuilder S_rev = new StringBuilder();
String S_r_v=S_rev.append(Math.abs(x)).reverse().toString();//.toString() String builder to String
double reverse_no=Double.parseDouble(S_r_v);
if (x < 0) {
return -(int)reverse_no;
}
return (int)reverse_no;
}
}
My Solution is ok for most of the test case. But it cannot pass one test case and I got a error
Error: Line 10: java.lang.NumberFormatException: For input string: "8463847412-"
If someone know what type of error it is please discuss.
Thank you in advance.
It seems like you are trying to pass in Integer.MIN_VALUE
When you pass in the minimum integer value, Math.abs seems to return a negative number as stated here
https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#abs-int-
Note that if the argument is equal to the value of Integer.MIN_VALUE, the most negative representable int value, the result is that same value, which is negative.
You can either check for x<=Integer.MIN_VALUE and return 0 if x is Integer.MIN_VALUE or handle the special case for Integer.MIN_VALUE
if(x== Integer.MIN_VALUE)
return -8463847412;
By converting number to String and reversing the sign symbol ended up on the end of the value. This makes the number invalid.
You don't have to convert to String or double. You can use module operator % to extract digits:
public int reverse(int x) {
long result = 0;
while (x != 0) {
result *= 10;
result += x % 10;
x /= 10;
}
if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) {
throw new IllegalArgumentException(); // overflow
}
return result;
}
If you necessarily want to implement it using StringBuilder, here it is:
public static void main(String[] args) {
ReverseNum reverseNum = new ReverseNum();
System.out.println(reverseNum.reverse(-123));
System.out.println(reverseNum.reverse(123));
System.out.println(reverseNum.reverse(0));
}
public int reverse(int x) {
int res = 1;
String xStr = String.valueOf(x);
StringBuilder builder = null;
if (xStr.startsWith("-")) {
builder = new StringBuilder(xStr.substring(1));
res = -1;
} else {
builder = new StringBuilder(xStr);
}
return res * Integer.valueOf(builder.reverse().toString());
}
Output:
-321
321
0
P.S. If you want to avoid integer overflow, then you can simply use long instead of int, like this:
public long reverse(int x) {
long res = 1;
String xStr = String.valueOf(x);
StringBuilder builder = null;
if (xStr.startsWith("-")) {
builder = new StringBuilder(xStr.substring(1));
res = -1;
} else {
builder = new StringBuilder(xStr);
}
return res * Long.valueOf(builder.reverse().toString());
}
public class ReverseString {
public static void main(String args[]) {
ReverseString rs = new ReverseString();
System.out.println(rs.reverse(-84638));
System.out.println(rs.reverse(5464867));
}
public long reverse(int number) {
boolean isNegative = number < 0;
StringBuilder reverseBuilder = new StringBuilder();
String reversedString = reverseBuilder.append(Math.abs(number)).reverse().toString();
long reversedStringValue = Long.parseLong(reversedString);
if(isNegative) {
return reversedStringValue * -1;
} else {
return reversedStringValue;
}
}
}
This code provides the output you have mentioned in the requirement. And It also supports for integer overflow. Your requirement is to convert int values. It is okay to get the converted value in the higher format since converted value may not be in the range of int. I have changed the reverse method return type to long.
I have identified a few issues in your code.
public int reverse(int x) {
if(x>Integer.MAX_VALUE || x<Integer.MIN_VALUE) {
return 0;
}
Above code segment, not point of checking whether the value is inside the int range because it is already received in the param as a string. It should throw an error before executing your code lines since it is not able to fit the larger value to int variable.
Finally, the int number you have used is not in the int range. (-8463847412)
What about this?
public class ReverseNumber {
public static void main(String[] args) {
System.out.println(reverse(123456));
System.out.println(reverse(0));
System.out.println(reverse(-987654));
}
private static int reverse(int i) {
final int signum;
if(i < 0) {
signum = -1;
} else {
signum = +1;
}
int reversedNumber = 0;
int current = Math.abs(i);
while(0 < current) {
final int cipher = current % 10;
reversedNumber = Math.addExact(Math.multiplyExact(reversedNumber, 10), cipher);
current = current / 10;
}
return signum * reversedNumber;
}
}
Output:
654321
0
-456789
This solution avoids strings and can handle negative numbers.
It throws an Arithmetic exception if an integer overflow happens.
I have bit representation like below
Bit 0(2^0 .= 1) - 1
Bit 1(2^1 .= 2) - 2
Bit 2(2^2 .= 4) - 4
Bit 3(2^3 .= 8) - 8
Bit 4(2^4 .= 16) - 16
A value of 7 means we have 1+2+4. But how do i get this array programmatically?
Continuosly divide by 2 and save the remainder
int n = 7;
StringBuilder sb = new StringBuilder();
while(n>0) {
sb.append(n%2);
n = n/2;
}
System.out.println(sb.reverse().toString());
You can store it anyway you want. Currently it is stored as string (Binary Representation of 7).
To convert back from the string to binary, start from LSB and add by powers of 2 of the bit position if the bit value is 1
Simple logic, works up to intmax (Very easy to change to max long by just changing type :))
public static void main(String[] args) {
int originalInt = 127;
toIntegerArray(originalInt);
}
private static List<Integer> toIntegerArray(int originalInt) {
String bits = Integer.toBinaryString(originalInt);
// Reversed, for easier logic when building string
StringBuilder s = new StringBuilder(bits).reverse();
char[] bitArray = s.toString().toCharArray();
List<Integer> result = new ArrayList<>();
for (int i = 0; i < bitArray.length; i++) {
if (bitArray[i] == '1') {
result.add((int) Math.pow(2, i));
}
}
System.out.println("Original int: " + originalInt);
System.out.println("Bit pattern: " + bits);
System.out.println(result);
return result;
}
I got below working, but for values below 31. Any suggestion on how to allow any value?
public static void Main(string[] args)
{
Console.WriteLine();
Console.WriteLine("[{0}]", string.Join(", ", log3(100)));
}
static int[] log3(int x) {
List<int> pow = new List<int>();
int val=x;
do{
if(x>= 1 << val){
if(1<<val>0){
pow.Add(1<<val);
}
x-=1<<val;
}
val-=1;
}while(val>=0);
return pow.ToArray();
}
Here is a recursive streaming option:
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Class {
private static IntStream intToBinaryParts(final int input, final int count) {
int powerOf2 = (int) Math.pow(2, count);
if (count < 0) {
return IntStream.empty();
} else if (input < powerOf2) {
return intToBinaryParts(input, count - 1);
} else {
return IntStream.concat(intToBinaryParts(input - powerOf2, count - 1), IntStream.of(powerOf2));
}
}
public static List<Integer> intToBinaryParts(final int input) {
return intToBinaryParts(input, (int) Math.ceil(Math.log(input) / Math.log(2)))
.mapToObj(Integer::new)
.collect(Collectors.toList());
}
public static void main(String... args) {
System.out.println(intToBinaryParts(7));
System.out.println(intToBinaryParts(8));
System.out.println(intToBinaryParts(100));
System.out.println(intToBinaryParts(1234567890));
}
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I'm very stuck on a project, so far I have got:
public class MyInt implements Comparable<MyInt> {
private int value;
MyInt(int x) {
value = x;
}
public String toString() {
return ("" + value);
}
public int intValue() {
return value;
}
public int compareTo(MyInt rhs) {
MyInt myInt = (MyInt) rhs;
int myInteger = myInt.intValue();
int result = 0;
if (value < myInteger) {
result = -1;
} else if (value == myInteger) {
result = 0;
} else {
result = +1;
}
return result;
}
}
And this is the question:
Consider the following Java Library interface:
public interface Comparable<T> {
int compareTo(T rhs);
}
Complete the implementation of the class below that implements the above
interface (note this interface is automatically imported by java – do NOT
re-type it in your project). The compareTo method should return -1 if
value is less than rhs.value, 0 if both sides are equal and +1 if value is
greater than rhs.value.
public class MyInt implements Comparable<MyInt> {
private int value;
MyInt(int x) {...}
public String toString() {...}
public int intValue() {...}
public int compareTo(MyInt rhs){...}
}
Now I need to implement the comparable interface in another class which performs basic arithmetic with rational numbers, would it be best to use inheritance to achieve this?The class :
public class Rational {
private int num;
private int denom;
public Rational() {
this(0,1);
}
public Rational(int num, int denom) {
this.num = num;
this.denom = denom;
}
int getNum() {
return num;
}
int getDenom() {
return denom;
}
public Rational add(Rational rhs) {
return new Rational(num * rhs.denom + rhs.num * denom, denom * rhs.denom);
}
public Rational subtract(Rational rhs) {
return new Rational(num * rhs.denom - rhs.num * denom, denom * rhs.denom);
}
public Rational multiply(Rational rhs) {
return new Rational(num * rhs.num, denom * rhs.denom);
}
public Rational divide(Rational rhs) {
return new Rational(num * rhs.denom, denom * rhs.num);
}
public String toString() {
String result;
if (num == 0)
result = "0";
else if (denom == 1)
result = num + "";
else
result = num + "/" + denom;
return result;
}
public static void main(String[] args) {
Rational r1 = new Rational(1, 2); // 1/2
Rational r2 = new Rational(3, 4);// 3/4
Rational result = new Rational();
result = r1.add(r2);
System.out.println(result);
Rational result1 = new Rational();
result1 = r1.subtract(r2);
System.out.println(result1);
Rational result2 = new Rational();
result2 = r1.multiply(r2);
System.out.println(result2);
Rational result3 = new Rational();
result3 = r1.divide(r2);
System.out.println(result3);
}
}
You need to compare this.intValue() (the current instance) and rhs.intValue() (the "right hand side"). Comparing rhs to itself (by aliasing it to myInt) should always return 0. And storing the result as a temporary variable doesn't seem to server any purpose in your code. You could do something like
// MyInt myInt = (MyInt) rhs;
if (this.intValue() < rhs.intValue()) {
return -1;
} else if (this.intValue() == rhs.intValue()) {
return 0;
}
return 1;
No need to do explicit casting of your parameter (MyInt rhs), and since you are simply comparing two integers, use static compare method from Integer:
public int compareTo(MyInt rhs) {
return Integer.compare(this.value, rhs.intValue());
}
I would suggest to change your int field to Integer to avoid performance loss in autoboxing of primitives
Is there a way to use a randomize function with relation to a give data type, i.e.
if I request the type is double then I will get double values, and if the requested type is float I will get float values?
Is there such a randomize function?
java 1.7:
Either you call ThreadLocalRandom.current().next<DataType>() by yourself, or you write a wrapper around this call:
import java.util.concurrent.ThreadLocalRandom;
//...
public static int nextRandom(int maxValueExclusive)
{
return ThreadLocalRandom.current().nextInt(maxValueExclusive);
}
public static long nextRandom(long maxValueExclusive)
{
return ThreadLocalRandom.current().nextLong(maxValueExclusive);
}
public static double nextRandom(double maxValueExclusive)
{
return ThreadLocalRandom.current().nextDouble(maxValueExclusive);
}
public static float nextRandom(float maxValueExclusive)
{
if (maxValueExclusive <= 0)
throw new IllegalArgumentException("argument must be positive: " + maxValueExclusive);
return ThreadLocalRandom.current().nextFloat()*maxValueExclusive;
}
public static boolean nextRandom(boolean unusedValue)
{
return ThreadLocalRandom.current().nextBoolean();
}
java 1.6:
import java.util.Random;
//...
private static final Random random = new Random(); // be careful with multiple threads
public static int nextRandom(int maxValueExclusive)
{
return random.nextInt(maxValueExclusive);
}
public static long nextRandom(long maxValueExclusive)
{
//implementation from java 1.7 ThreadLocalRandom
if (maxValueExclusive <= 0)
throw new IllegalArgumentException("argument must be positive: " + maxValueExclusive);
// Divide n by two until small enough for nextInt. On each
// iteration (at most 31 of them but usually much less),
// randomly choose both whether to include high bit in result
// (offset) and whether to continue with the lower vs upper
// half (which makes a difference only if odd).
long offset = 0;
while (maxValueExclusive >= Integer.MAX_VALUE) {
long half = maxValueExclusive >>> 1;
long nextn = random.nextBoolean() ? half : maxValueExclusive - half;
if (random.nextBoolean())
offset += maxValueExclusive - nextn;
maxValueExclusive = nextn;
}
return offset + random.nextInt((int) maxValueExclusive);
}
public static double nextRandom(double maxValueExclusive)
{
if (maxValueExclusive <= 0)
throw new IllegalArgumentException("argument must be positive: " + maxValueExclusive);
return random.nextDouble()*maxValueExclusive;
}
public static float nextRandom(float maxValueExclusive)
{
if (maxValueExclusive <= 0)
throw new IllegalArgumentException("argument must be positive: " + maxValueExclusive);
return random.nextFloat()*maxValueExclusive;
}
public static boolean nextRandom(boolean unusedValue)
{
return random.nextBoolean();
}
Can anyone help me compare an Integer to a Double using generics?
This is what I have:
public static <T extends Comparable<? super T>> int compare(T arg1, T arg2)
{
return arg1.compareTo(arg2);
}
public static void main(String[] args)
{
Number i = new Integer(5);
Number j = new Double(7);
System.out.println(GenericsTest.compare(i, j));
}
The error message I get is:
Bound mismatch: The generic method compare(T, T) of type GenericsTest is not applicable for the arguments (Number, Number). The inferred type Number is not a valid substitute for the bounded parameter >
The idea of this solution is to widen to BigDecimal and then compare the two numbers (now is cleaner but somehow formatting doesn't work). Note you may reuse this static comparator without having to cast to double anywhere else. In the implementation you do need conversion to double not to lose information, basically you widen to the most general representation.
private static final Comparator<Number> NUMBER_COMPARATOR = new Comparator<Number>() {
private BigDecimal createBigDecimal(Number value) {
BigDecimal result = null;
if (value instanceof Short) {
result = BigDecimal.valueOf(value.shortValue());
} else
if (value instanceof Long) {
result = BigDecimal.valueOf(value.longValue());
} else
if (value instanceof Float) {
result = BigDecimal.valueOf(value.floatValue());
} else
if (value instanceof Double) {
result = BigDecimal.valueOf(value.doubleValue());
} else
if (value instanceof Integer) {
result = BigDecimal.valueOf(value.intValue());
} else {
throw new IllegalArgumentException("unsupported Number subtype: " + value.getClass().getName());
}
assert(result != null);
return result;
}
public int compare(Number o1, Number o2) {
return createBigDecimal(o1).compareTo(createBigDecimal(o2));
};
};
public static void main(String[] args) {
Number i = Integer.valueOf(5);
Number j = Double.valueOf(7);
// -1
System.out.println(NUMBER_COMPARATOR.compare(i, j));
i = Long.MAX_VALUE;
j = Long.valueOf(7);
// +1
System.out.println(NUMBER_COMPARATOR.compare(i, j));
i = Long.MAX_VALUE;
j = Long.valueOf(-7);
// +1
System.out.println(NUMBER_COMPARATOR.compare(i, j));
i = Long.MAX_VALUE;
j = Double.MAX_VALUE;
// -1
System.out.println(NUMBER_COMPARATOR.compare(i, j));
i = Long.MAX_VALUE;
j = Long.valueOf(Long.MAX_VALUE - 1);
// +1
System.out.println(NUMBER_COMPARATOR.compare(i, j));
// sorting Long values
Long[] values = new Long[] {Long.valueOf(10), Long.valueOf(-1), Long.valueOf(4)};
Arrays.sort(values, NUMBER_COMPARATOR);
// [-1, 4, 10]
System.out.println(Arrays.toString(values));
}
As aready said in the comments, Number does not implement Comparable.
But Double and Integer do.
One way to make this work is like this:
public static <T extends Comparable<? super T>> int compare(T arg1, T arg2)
{
return arg1.compareTo(arg2);
}
public static void main(String[] args)
{
Double i = new Integer(5).doubleValue();
Double j = new Double(7);
System.out.println(GenericsTest.compare(i, j));
}
Number doesn't implement Comparable.
Declare both variables as Integer.
private boolean compareObject(Object expected, Object actual) {
if (expected instanceof Number && actual instanceof Number) {
double e = ((Number) expected).doubleValue();
double a = ((Number) actual).doubleValue();
return e == a;
} else {
return com.google.common.base.Objects.equal(expected, actual);
}
}
Create a class that implements Comparable which takes a Number in the constructor.
e.g.
public class GenericNumber implements Comparable<GenericNumber> {
private Number num;
public GenericNumber(Number num) {
this.num = num;
}
// write compare function that compares num member of two
// GenericNumber instances
}
Then simply do this:
GenericNumber i = new GenericNumber(new Integer(5));
GenericNumber j = new GenericNumber(new Double(7));
System.out.println(GenericsTest.compare(i,j));