I have written the following code:
public String alphabets = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ#$%";
public Integer findBase(String input) {
int i = 0;
Integer base = 0;
Integer temp = 0;
while (i != input.length()) {
temp = alphabets.indexOf(input.charAt(i)) + 1;
if (temp > base) {
base = temp;
}
i ++;
}
public String convert(String input, Integer to_base, Integer from_base) {
int i;
Long base_ten = 0L;
Integer input_base = 0;
// If specified, then consider that base as input from base, or else,
// calculate the base of the number
if (from_base == 0) {
input_base = findBase(input);
} else {
input_base = from_base;
}
Integer power = 0;
Double temp_power = 0.0;
while (!input.equals("")) {
temp_power = Math.pow(input_base, power);
base_ten = base_ten + alphabets.indexOf(input.charAt(input.length() - 1)) * temp_power.intValue();
input = input.substring(0, input.length() - 1);
power = power + 1;
}
Long rem = 0L;
String result = "";
while (base_ten != 0L) {
rem = base_ten % to_base;
base_ten = base_ten / to_base;
result = result + alphabets.charAt(rem.intValue());
}
String reverse = new StringBuffer(result).reverse().toString();
return reverse;
}
Using the above code, it is possible to convert strings like say "suchin" (Base 31) to other bases. But whenever I use something larger, like say "suchind", I get an exception at the following line in above code:
result = result + alphabets.charAt(rem.intValue());
saying that the index is -1. When I dug a little deeper, I felt that rem.intValue() is somehow going negative (-1) for some large values. Not sure how to get this solved. Is there a way of converting between bases for large numbers in java?
BigInteger version of code is below:
public String convert(String input, BigInteger to_base, BigInteger from_base) {
int i;
BigInteger base_ten = new BigInteger("0");
BigInteger input_base = new BigInteger("0");
if (from_base.equals(BigInteger.valueOf(0))) {
input_base = BigInteger.valueOf(findBase(input));
} else {
input_base = from_base;
}
BigInteger power = new BigInteger("0");
BigInteger temp_power = new BigInteger("0");
BigInteger to_add = new BigInteger("0");
while (!input.equals("")) {
temp_power = input_base.pow(power.intValue());
to_add = BigInteger.valueOf(alphabets.indexOf(input.charAt(input.length() - 1)));
to_add = to_add.multiply(temp_power);
base_ten = base_ten.add(to_add);
input = input.substring(0, input.length() - 1);
power = power.add(BigInteger.valueOf(1));
}
BigInteger rem = new BigInteger("0");
String result = "";
while (!base_ten.equals(BigInteger.valueOf(0))) {
rem = base_ten.remainder(to_base);
base_ten = base_ten.divide(to_base);
result = result + alphabets.charAt(rem.intValue());
}
String reverse = new StringBuffer(result).reverse().toString();
return reverse;
}
The above code works fine now. Earlier I had done the following:
while( base_ten != BigInteger.valueOf(0)) {
Which was causing infinite loop, as apparently that was not the way to compare in BigIntegers :)
Related
I am trying to write a simple code for polynomial multiplication. I think it is logical to take inputs as strings such as "3x^2".
Problem is I don't know what to do with the 'x's in it. How can I turn them into something that can be multiplied? What should the logic be? I am totally new in Java and I really need help.
For example:
String s = "x^2";
String s2 = "3x^5";
//(Multiply them)
result = 3x^7
public static int[] multiply(String term1, String term2)
{
int[] t1 = parse(term1);
int[] t2 = parse(term2);
int[] ret = new int[2];
ret[0] = t1[0] * t2[0];
ret[1] = t1[1] + t2[1];
return ret;
}
public static int[] parse(String term)
{
int pos = term.indexOf("x^");
String coeffStr = term.substring(0, pos);
int coeff = Integer.parseInt(coeffStr);
String powerStr = term.substring(pos + 2);
int power = Integer.parseInt(powerStr);
int[] ret = new int[2];
ret[0] = coeff;
ret[1] = power;
return ret;
}
This will work for multiplying polynomials in the format Ax^n, x^n or Ax. I would put the terms you want to multiply into a List, and then parse the coefficients and powers into a HashMap, then use those to get you get your final result
List<String> terms = new ArrayList<>(Arrays.asList("x^2", "3x^5", "5x"));
Map<Integer,Integer> map = new HashMap<>();
for ( String term : terms ) {
String coefficient = term.split("x")[0].matches("") ? "1" : term.split("x")[0];
String[] exponent = term.split("x");
String power = exponent.length > 1 ? exponent[1].split("\\^")[1] : "1";
map.put(Integer.parseInt(coefficient), Integer.parseInt(power));
}
Integer finalCoefficient = 1;
Integer finalPower = 0;
for ( Integer coefficient : map.keySet() ) {
finalCoefficient *= coefficient;
finalPower += map.get(coefficient);
}
System.out.println(finalCoefficient + "x" + finalPower);
This is for a fraction class. When i test the fraction class with a string like "2/4" I get the following exception:
java.lang.NumberFormatException: For input string: "".
I think it has something to do with the sStringTo method when trying to replace spaces.
public class Util{
static int findGCF(int a, int b){
a = Math.abs(a);
b = Math.abs(b);
while(a != b){
if (a>b) a = a-b; else b = b-a;
}
return (a);
}
static Fraction sIntTo(String s){ //"2"
int n = Integer.parseInt(s);
return new Fraction(n);
}
static Fraction sFractionTo(String s){ //"2/3"
s = s.trim();
int posSlash = s.indexOf("/");
int n = Integer.parseInt(s.substring(0,posSlash));
int m = Integer.parseInt(s.substring(posSlash + 1));
return new Fraction(n,m);
}
static Fraction sMixTo(String s){
s =s.trim();
int posB = s.indexOf(" ");
int posSlash = s.indexOf("/");
int w = Integer.parseInt(s.substring(0,posB));
int t = Integer.parseInt(s.substring(posB+1, posSlash));
int b = Integer.parseInt(s.substring(posSlash+1));
return new Fraction(w*b+t,b);
}
static Fraction sDecTo(String s){
s = s.trim();
int i = s.indexOf(".");
String sub = s.substring(i+1);
String sNoPeriod = s.substring(0,i) + sub;
int top = Integer.parseInt(sNoPeriod);
int bot = 1;
for(int j = 0; j<sub.length(); j++) bot = bot*10;
return new Fraction(top,bot);
}
static Fraction divFraction(Fraction f, Fraction g){
return new Fraction (f.num * g.den, f.den * g.num);
}
static Fraction addFraction(Fraction f, Fraction g){
return new Fraction (f.num * g.den + f.den * g.num, f.den*g.den);
}
static Fraction sStringTo(String s){
s=s.trim();
s= s.replaceAll("\\s*/\\S*", "/");// remove 0 or more blanks before & after slash
s = s.replaceAll("\\s+", " "); // all blanks to be one blank: 2 1/2
int posB = s.indexOf(" ");
int posSlash = s.indexOf("/");
int posPed = s.indexOf(".");
Fraction ans = null;
if(posB>-1){
if (posSlash>posB) { ans = sMixTo(s);}
}else{
if (posPed == -1 && posSlash == -1) ans = sIntTo(s); //integer only
else{
if(posSlash == -1) ans = sDecTo(s);// decimal only
else{
//with slash "2.1/2 2.1/2.1
Fraction f = sStringTo(s.substring(0,posSlash));
Fraction g = sStringTo(s.substring(posSlash+1));
ans = divFraction(f,g);
}
}
}
return ans;
}//sStringTo()
The problematic stack trace is:
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Integer.parseInt(Integer.java:662)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at Util.sIntTo(Util.java:17)
at Util.sStringTo(Util.java:75)
at Util.sStringTo(Util.java:81)
at Fraction.<init>(Fraction.java:31)
at Test.main(Test.java:6)
It looks like you are passing a string containing only whitespace into sIntTo(). You should consider just removing all whitespace, rather than just reducing it to a single space. Consider changing s = s.replaceAll("\\s+", " "); to s = s.replaceAll("\\s+", "");.
I figured out the problem. It was a syntax error on my part.
How to best print 2 float numbers in scientific-notation but with same exponent?
eg: I'd like to print numbers like this:
1.234e-6
11.234e-6
And I would like some function to detect automatically best exponent - that is smaller number always start at first decimal digit and bigger number prints how it must with same exponent.
eg: 0.1 and 100 would print
1.000e-1
1000.000e-1
But even when I ask explicitly for 2 decimal places String.format("%2.3e",11.234e-6) I got 1.123e-5
So far I come up with code bellow. It works as I want. But as you can see it is not exactly short or swift... It would be great if someone would point to some Java native functions which helps me to do it more elegant...
public static String repeat(int count, String with) {
if(count<0){
return "";
}
if(count>1e5){
return "";
}
return new String(new char[count]).replace("\0", with);
}
public static String getFormattedDouble(double num,int posInt,int posFrac){
if(num == 0) return "0"; // correct 0 value to be print only with one 0
String sInt = repeat(posInt,"0");
String sFrac = repeat(posFrac,"0");
String sSing = num<0 ? "" : "+";
DecimalFormat form = new DecimalFormat(sSing+sInt+"."+sFrac+"E0");
String s = form.format(num);
s = s.replace("E","e"); // I really thing capital E looks ugly
return s;
}
public static String[] get2doublesSameExp(double a, double b){
String[] s = new String[2];
int expA;
if(a == 0) expA = 0;
else expA = (int)Math.floor(Math.log10(Math.abs(a)));
int expB;
if(b == 0) expB = 0;
else expB = (int)Math.floor(Math.log10(Math.abs(b)));
double expDif = Math.abs((double)expA-(double)expB);
int fractPos = 3;
if(expDif > 4) fractPos = 1; // too big exponent difference reduce fraction digits
if(expDif > 6){
// too big exponent difference print it normally it will be nicer
s[0] = String.format("%1.3e",a);
s[1] = String.format("%1.3e",b);
return s;
}
int minExp = Math.min(expA,expB) - 1;
s[0] = getFormattedDouble(a, expA - minExp, fractPos );
s[1] = getFormattedDouble(b, expB - minExp, fractPos );
// just text right justification
String rightJust = repeat((int)expDif," ");
int justIdx = expA < expB ? 0 : 1;
s[justIdx] = rightJust + s[justIdx];
return s;
}
String[] s = get2doublesSameExp(1.234e-6,11.234e-6);
I currently do a lot of conversions from int into a base36 string (70%~ of programs time).
Are there any obvious optimisations to this code?
public static final String alphabet = "0123456789abcdefghijklmnopqrstuvwxyz";
public static StringBuilder b = new StringBuilder();
public static String sign = "";
public static String convertToBase36(int number)
{
if (number == 0)
{
return "0";
}
b.delete(0, b.length());
sign = "";
if (number < 0)
{
sign = "-";
number = -number;
}
int i = 0;
int counter = 10;
while (number != 0 && counter > 0)
{
counter--;
i = number % 36;
number = (number - i)/36;
b.append(alphabet.charAt(i));
}
return sign + b.reverse().toString();
}
You can use:
String s = Integer.toString(100, 36);
int i = Integer.parseInt("2s", 36);
Easier to maintain, and probably well optimized.
I was hoping somebody could help me with with this. I am trying to add a constructor to allow the input of polynomial data from a string in the form 3x^y and put the coefficient, variable, and exponent values into the corresponding variables defined in a class. The constructor I have implemented allows the program to compile, but will freeze when running the application if...
this:
trinomial[0] = new Term (3,'x',2);
is set to:
trinomial[0] = new Term ("3x^y");
Basically, I'm trying to get the defined class to accept both forms of input (string and double/char/exponent formats). Any help with this would be greatly appreciated.
public class TrinomialTest {
static void printTrinomial(Term[] x) {
for (int i = 0; i < x.length; i++) {
//AUTOMATICALLY CALLS TOSTRING() WHEN PRINTLN
System.out.print(x[i]);
}
}
public static void main(String[] args) {
Term[] trinomial = new Term[3];
trinomial[0] = new Term(3, 'x', 2);
trinomial[1] = new Term(12, 'x', 1);
trinomial[2] = new Term(-23, 'x', 0);
printTrinomial(trinomial);
}
}
class Term {
private double coefficient; //the number
private char variable; // the letter
private int exponent;
public Term(double c, char v, int e) {
coefficient = c;
variable = v;
exponent = e;
}
//New Constructor
public Term(String Term) {
String c = "";
String v = "";
String e = "";
int exponentIndex = 0;
exponentIndex = Term.indexOf("^");
if (Term.substring(0, 1).matches("[0-9]")) {
c = Term.substring(0, 1);
v = Term.substring(1, 2);
} else {
c = "0";
v = Term.substring(0, 1);
}
do {
e = Term.substring(exponentIndex, exponentIndex + 1);
} while (Term.indexOf("^") != -1);
coefficient = Double.parseDouble(c);
variable = v.charAt(0);
exponent = Integer.parseInt(e);
}
public String toString() {
int c = (int) coefficient;
if (exponent == 1 && c > 0)
return ("" + "+" + c + variable);
else if (exponent == 1 && c < 0)
return ("" + c + variable);
else if (exponent == 0 && c > 0)
return ("" + "+" + c);
else if (exponent == 0 && c < 0)
return ("" + c);
return ("" + c + variable + "^" + exponent);
}
}
Simple solution:
String term = "32x^33";
String[] tokens = term.split("\\^");
String coeff = tokens[0].substring(0, tokens[0].length()-1);
String var = tokens[0].substring(tokens[0].length()-1, tokens[0].length());
String exp = tokens[1];
System.out.println("coeff = "+coeff+", var = "+var+", exp = "+exp);