multiplying bigintegers without bigintegers - java

Hey' all so im figuring out how to multiply bigintegers without importing them and I have it almost all. The only thing that isnt working is when multiplying with -digit the output is still +. any help appreciated. ie. -20*4=80
Scanner scan = new Scanner(System.in);
System.out.println("Type the first number:");
String x = scan.nextLine();
System.out.println("Type the second number:");
String y = scan.nextLine();
if (x.charAt(0) == '-' && y.charAt(0) != '-') {
x = x.substring(1);
}
else if (x.charAt(0) != '-' && y.charAt(0) == '-') {
y = y.substring(1);
}
else if (x.charAt(0) == '-' && y.charAt(0) == '-') {
x = x.substring(1);
y = y.substring(1);
}
String s1 = new StringBuffer(x).reverse().toString();
String s2 = new StringBuffer(y).reverse().toString();
int[] m = new int[s1.length() + s2.length()];
for (int i=0; i<s1.length(); i++) {
for (int j=0; j<s2.length(); j++) {
m[i+j] = m[i+j] + (s1.charAt(i) - '0') * (s2.charAt(j) - '0');
}
}
String product = new String();
for (int i=0; i<m.length; i++) {
int digit = m[i] % 10;
int carry = m[i] / 10;
if (i+1 < m.length) {
m[i+1] = m[i+1] + carry;
}
product = digit + product;
}
while (product.length() > 1 && product.charAt(0) == '0') {
product = product.substring(1);
}
if (x.charAt(0) == '-' && y.charAt(0) != '-') {
product = new StringBuffer(product).insert(0, '-').toString();
}
else if (x.charAt(0) != '-' && y.charAt(0) == '-') {
product = new StringBuffer(product).insert(0, '-').toString();
}
else if (x.charAt(0) == '-' && y.charAt(0) == '-') {
product = product;
}
System.out.println("The multiplication of\n" + x + " \nand\n" + y + " " + "\nis\n" + product);
scan.close();
}
}

You're removing the negative symbol from the numbers here:
if (x.charAt(0) == '-' && y.charAt(0) != '-') {
x = x.substring(1);
}
else if (x.charAt(0) != '-' && y.charAt(0) == '-') {
y = y.substring(1);
}
So after those lines your x and y variables no longer contain the negative symbol.
So when you're checking it near the end here:
if (x.charAt(0) == '-' && y.charAt(0) != '-') {
product = new StringBuffer(product).insert(0, '-').toString();
}
else if (x.charAt(0) != '-' && y.charAt(0) == '-') {
product = new StringBuffer(product).insert(0, '-').toString();
}
else if (x.charAt(0) == '-' && y.charAt(0) == '-') {
product = product;
}
It will never get into any of the conditions.
One good way to debug this on your end is to set a breakpoint within the condition you think it should drop into and see if it's hit. Or breakpoint before the conditions and examine the variables to ensure they are what you expect them to be. You could also throw some println statements in there temporarily just to say "I got into this conditional".
The adjustment I'd recommend making is holding onto whether each number was negative before stripping the negative so you can use that in your logic later on.
Here's the adjustment which should accomplish what you want. I used Integers instead of bools to make the check for whether to apply the negative symbol later easier (i.e. isFirstNumberNegative + isSecondNumberNegative == 1)
Scanner scan = new Scanner(System.in);
System.out.println("Type the first number:");
String x = scan.nextLine();
System.out.println("Type the second number:");
String y = scan.nextLine();
// hold onto which numbers are negative
Integer isFirstNumberNegative = x.charAt(0) == '-' ? 1 : 0;
Integer isSecondNumberNegative = y.charAt(0) == '-' ? 1 : 0;
// strip the negative symbols from the numbers which are negative
if (isFirstNumberNegative > 0) {
x = x.substring(1);
}
if (isSecondNumberNegative > 0) {
y = y.substring(1);
}
String s1 = new StringBuffer(x).reverse().toString();
String s2 = new StringBuffer(y).reverse().toString();
int[] m = new int[s1.length() + s2.length()];
for (int i=0; i<s1.length(); i++) {
for (int j=0; j<s2.length(); j++) {
m[i+j] = m[i+j] + (s1.charAt(i) - '0') * (s2.charAt(j) - '0');
}
}
String product = new String();
for (int i=0; i<m.length; i++) {
int digit = m[i] % 10;
int carry = m[i] / 10;
if (i+1 < m.length) {
m[i+1] = m[i+1] + carry;
}
product = digit + product;
}
while (product.length() > 1 && product.charAt(0) == '0') {
product = product.substring(1);
}
// if only one number is negative put a negative symbol in front
// if both numbers are negative this condition won't hold true because it will be == 2
// if both numbers are positive this condition won't hold true because it wil be == 0
if (isFirstNumberNegative + isSecondNumberNegative == 1) {
product = new StringBuffer(product).insert(0, '-').toString();
}
System.out.println("The multiplication of\n" + x + " \nand\n" + y + " " + "\nis\n" + product);
scan.close();

Just remove the symbols from the numbers and save them. Then later, use them to determine if a negative is required. An exclusive or test for - is all that is necessary for a negative result.
You can create a record (or a class) to return the numbers and resulting sign, ready for processing.
record Numb(String sign,String num1, String num2) {}
String n1 = "-2123";
String n2 = "+2343";
Numb n = prepNums(n1,n2);
System.out.println(n.sign + ", " + n.num1 + " " + n.num);
Prints
-, 2123, 2343
After multiplying, just prepend the sign to the result. Note that the default positive sign is no sign.
And here is the method that processes the strings and returns
them and the resultant sign for multiplication.
public static Numb prepNums(String n1, String n2) {
boolean sign1 = false;
boolean sign2 = false;
char firstChar = n1.charAt(0);
if (!Character.isDigit(firstChar)) {
sign1 = firstChar == '-';
n1 = n1.substring(1); // remove sign
}
firstChar = n2.charAt(0);
if (!Character.isDigit(firstChar)) {
sign2 = firstChar == '-';
n2 = n2.substring(1); // remove sign
}
return new Numb( (sign1 ^ sign2) ? "-" : "", n1, n2);
}

just speaking in a generic concept sense - the square root of largest safe unsigned int,
4^3^3/2-1
is approx 94906265.6242. So right off the bat you know you don't have 8-full decimal digits width to work with unless you add in special tricks.
All those fancy algorithms they talk about - they frequently waste your time by having to first convert from decimal to binary, do the math, then re-convert it back out.
I just split mine into chunks of 7-digits wide, so the the maximum multiply result per op is capped at just shy of 10^14
- for 7 9's squaring each other, approx. 46.50699304-binary bits
- for 8 9's squaring ………. is approx. 53.15084949 bits
for whatever slowness one might believe in simpleton grade school multiply, you more than gain back the savings by avoiding a bidirectional base-conversion.

Related

Certain Switch Cases not printing Java

I have a Switch statement within a loop where I am trying to print a random math operation in an equation multiple times. The whole code is quite long, so I'm hoping this is enough to answer my question.
I know for certain that the fifth case '%' does not work.
Here is my output
num1 = random.nextInt(max + 1 - min) + min;
num2 = random.nextInt(max + 1 - min) + min;
char op = switch (getOper(year)) {
case 1 -> '+';
case 2 -> '-';
case 3 -> '*';
case 4 -> '/';
case 5 -> '%';
default -> ' ';
};
//prints out the questions
System.out.print(num1 + " " + op + " " + num2 + " = ");
private int getOper(int year){
//sets the operatorBounds variable to zero
int operatorBounds = 1;
//creates a new random object
Random bounds = new Random();
int oper = 0;
//determines how many operations are available to each year level
if (year == 1 || year == 2){
operatorBounds = 2;
oper = bounds.nextInt(operatorBounds);
} else if (year == 3 || year == 4 || year == 5){
operatorBounds = 4;
oper = bounds.nextInt(operatorBounds);
} else if (year == 6 || year == 7){
operatorBounds = 5;
oper = bounds.nextInt(operatorBounds);
}
return oper;
}
This is the output I'm receiving:
6674 2640 = 1560 + -5740 = 1274 6126 =
The spaces are where the operator is supposed to be
If anyone can help I'd really appreciate it!

Read number as string sequence and convert first and last to an Integer

I'm new to programming and I've just started learning Java.
I want to do a program that's
asks the user to enter a string that contains a sequence of numbers and then
takes the first and the last numbers of that sequence and
check if these numbers are an odd or even
Based on that information it will do certain things.
Here's my code:
public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
String n = kb.nextLine();
Integer x = Integer.valueOf(n.charAt(n.length() - 1));
Integer y = Integer.valueOf(n.charAt(0));
String out;
if (y % 2 == 0 && x % 2 == 0) {
out = "$" + n.substring(1, n.length() - 1) + "$";
} else if (y % 2 > 0 && x % 2 > 0) {
out = "X" + n.substring(1, n.length() - 1) + "X";
} else if (x == 0); {
out = n.substring(0, n.length() - 1) + "#";
}
System.out.println(out);
}
I'm not sure what's the problem. I think its about those two lines
Integer x = Integer.valueOf(n.charAt(n.length()-1));
Integer y = Integer.valueOf(n.charAt(0));
The output value is different than the one in the input..
The Scanner code can be improve and there is indeed a problem with your conversion. Your code gets the ASCII value of those symbols. Try it like this:
public static void main (String[] args) throws java.lang.Exception
{
Scanner console = new Scanner(System.in);
while (console.hasNextLine()) {
String n = console.nextLine();
Integer x = Integer.parseInt(n.substring(n.length()-1));
//System.out.println(x);
Integer y = Integer.parseInt(n.substring(0, 1));
//System.out.println(y);
String out;
if (y % 2 == 0 && x % 2 == 0)
{
out = "$"+n.substring(1, n.length()-1)+"$";
}
else if (y % 2 > 0 && x % 2 > 0) {
out = "X" +n.substring(1, n.length()-1) + "X";
}
else if (x == 0);
{
out = n.substring(0, n.length()-1)+ "#";
}
System.out.println(out);
}
}
Online Demo
I've used substring()/parseInt() but there are many ways to convert a string or char to an Integer.

check isbn 10 number java

I should make a programm to control the number of an isbn 10 number. Therefore I'm not allowed to use arrays andd the input of the number has to be a char. The In method is similar to java scanner.
public class ISBN {
public static void main(String[] args) {
System.out.println("ISBN - Pruefung");
System.out.println("=================");
System.out.print("ISBN-Nummer: ");
char isbn = In.read();
int check = 0;
int d=0;
for (d=0; d<10; d++) {
if ('0' <= isbn && isbn <= '9' ) {
check = (int) ((isbn-48)*d)+check;
if(d ==9) {
int lastDigit = check%11;
if(lastDigit ==10) {
System.out.println("x");
}else {
System.out.println(lastDigit);
}
}else {
System.out.print(isbn);
}
}else {
System.out.println(isbn + "Falsche Eingabe");
System.exit(0);
}
isbn = In.read();
}
if (d == 10 && check%11 ==0) {
System.out.println("wahr");
}else {
System.out.println("falsch");
}
}
}
I googled some isbn 10 numbers but my programs says they are wrong (example 2123456802). Now my question where is my mistake and/or understood I the function of the last number wrong?
the sum of all the ten digits, each multiplied by its (integer) weight, descending from 10 to 1, is a multiple of 11.
So you just need to sum that digit value time the weight :
int check = 0;
for(int weight = 10; weight > 0; weigth--){
char c = In.read(); //get the next character
int i;
if( c == 'x' || c == 'X' ){
i = 10;
} else {
if(! Character.isDigit(c)) //Because, just in case...
throw new IllegalArgumentException("Not a numeric value");
i = Character.getNumericValue( c );
}
check += i * weight;
}
Just need to check if it is a multiple of 11
if ( check % 11 == 0 )
System.out.println( "VALID" );
else
System.out.println( "INVALID" );

Entering an if statement

In this segment of code, from everything I'm seeing, it should be entering the for loop and then the if statement as long as you enter 1's and 0's, which is what I'm doing. It's not entering it, as I've seen from my print statements.
I don't see a reason why.
If it did enter the if statement, I also am unsure what to do because my suspicion is that it will only set true if the last bit is not a 1 or 0: my intention being for zeroesAndOnes to be false if anything except 1's and 0's are entered. However, as it stands, it's false all the time.
System.out.println("Please enter a 32 bit number consisting of "
+ "1's and 0's.");
String number = kb.nextLine();
int count = 0;
boolean zeroesAndOnes = false;
for(int i = 0; i < number.length(); i++){
if(number.charAt(i) == '0' || number.charAt(i) == '1'){
zeroesAndOnes = true;
System.out.println("If boolean " + zeroesAndOnes);
}
else{
zeroesAndOnes = false;
count++;
}
}
System.out.println("If boolean end " + zeroesAndOnes);
if(number.length() == 32 && count > 1){
if(number.charAt(0) + number.charAt(1) % 2 == 1){
symmDiff = 1;
}
else{
symmDiff = 0;
}
for(int i = 2; i < number.length(); i++){
if((symmDiff + number.charAt(i)) % 2 == 1){
symmDiff = 1;
}
else{
symmDiff = 0;
}
}
System.out.println("The parity bit for this number is " + symmDiff);
}
else{
System.out.println("These numbers do not match the specification.");
}
When checking for char equality, be sure the comparison is what you need. For instance
if(number.charAt(i) == 0)
checks for decimal value equality. To check for an actual '0' char, compare the char value
if ( number.charAt(i) == '0' )
for comparing a char you should use
if(number.chartAt(i) == '0')
another issue is number.charAt(0) will give you char not int. so when you are doing
number.charAt(0)+number.charAt(1) //you are concatenating character at index 0 and index 1
// do this
int first = Integer.parseInt(number.substring(0,1));
int second = Integer.parseInt(number.substring(1,2));
if( (first+second)%2 == 1){
// your statement
}

How to solve an expression from user input not using parentheses?

I'm trying to write a program that evaluates an expression the user inputs. I know I need to have separate methods so It evaluates multiplication and division first then adds the addition and subtraction afterwards. This is what I got so far. When I try anything involving multiplication or division, like 6*6, it will only print the first character, which would be just '6' in this instance. Any ideas?
import java.util.Scanner;
class Expressions {
String e;
void setExpressions(String exp) {
e = exp;
}
String evaluate() {
String n = "";
for (int i = 0; i < e.length(); i++)
if (e.charAt(i) == '*' || e.charAt(i) == '/') {
n += e.charAt(i);
}
else if (e.charAt(i) == '+' || e.charAt(i) == '/') {
evaluateMD();
n = "";
}
else
n += e.charAt(i);
return n;
}
int evaluateMD () {
int r = 1;
int n = 0;
char op = '*';
for (int i = 0; i < evaluate().length(); i++)
if (evaluate().charAt(i) == '*' || evaluate().charAt(i) == '/') {
if (op == '*')
r *= n;
else
r /= n;
n = 0;
op = evaluate().charAt(i);
}
else if (evaluate().charAt(i) == '*' || evaluate().charAt(i) == '/')
n = 0;
else //digits
n = n*10 + (evaluate().charAt(i)-'0');
if (op == '+') //last operation
r *= n;
else
r /= n;
return r;
}
int evaluateAS() {
//e has +, - only, multiple digit numbers
int r = 0;
int n = 0;
char op = '+';
for (int i = 0; i < e.length(); i++)
if (e.charAt(i) == '+' || e.charAt(i) == '-') {
if (op == '+')
r += n;
else
r -= n;
n = 0;
op = e.charAt(i);
}
else if (e.charAt(i) == '*' || e.charAt(i) == '/')
n = 0;
else //digits
n = n*10 + (e.charAt(i)-'0');
if (op == '+') //last operation
r += n;
else
r -= n;
return r;
}
}
public class hw10 {
public static void main(String[] args) {
Scanner in = new Scanner (System.in);
Expressions myE = new Expressions();
System.out.print("Enter E:");//E for expression
String e = in.next();
myE.setExpressions(e);
//int r = myE.evaluate1();
int r = myE.evaluateAS();
System.out.println(e+" = "+r);
}
}
If I needed to write arithmetic expressions parser, I would use pretty simple approach: get the input from user, translate it into reverse polish notation (take a look at section named Shunting-yard algorithm), and evaluate it.
Robert Lafore in his "Data Structures and Algorithms in Java" has pretty easy explanation of both algorithms - translation from infix to RPN and evaluation of expressions written in RPN, with the source code, so you can see how it can be implemented. After you read it, it'll be easy to mix both algorithms into one - take a look at one of my questions on this topic.
Changing the line
if (op == '+') //last operation
in the evaluateMD method to
if (op == '*') //last operation
,changing the return type of the method to double and making r and n doubles produces better results for the evaluateMD, but really you're overall procedure needs an overhaul, if not complete abandonment.
I think your it would be better if your evaluate method only returned the answer to the calculation.
It would only ever need to store 2 values at most: (in the case that you have an AS operation you would store it if the next operator was MD since MD needs to be evaluated first, but once the MD operation (which could involve more than one operator or more than one instance of the same operator i.e. 4*5*6 or 4/3*2) is computed you can then perform the 'waiting' AS immediately. For MD operations, you'd just store the latest update each time, as you almost had working in your evaluateMD method (which I think works with the modification I put at the top. If it doesn't feel free to ask me about it as I did make a few other changes).
This is an improvement on the method you were attempting, but as I said there may well be methods which are better still mentioned in other answers.

Categories