The purpose of my code is to write a program that computes the following summation series using the Rational class: 1/2 + 2/3 + 3/4 + ... + 99/100.
My code is shown as follows:
import java.math.BigInteger;
public class Exercise {
public static void main(String[] args){
final BigInteger N = new BigInteger("99");
RationalV8 sum = new RationalV8();
for (BigInteger i = BigInteger.ONE; i.compareTo(N) <= 0; i = i.add(BigInteger.ONE)){
sum = sum.add(new RationalV8(i, i.add(BigInteger.ONE)));
}
System.out.println("The sum : " + sum + " = "
+ sum.doubleValue());
}
}
class RationalV8 extends Number implements Comparable <RationalV8>{
private BigInteger numerator = BigInteger.ZERO;
private BigInteger denominator = BigInteger.ONE;
public RationalV8(){
this(BigInteger.ZERO, BigInteger.ONE);
}
public RationalV8( BigInteger numerator, BigInteger denominator){
BigInteger gcd = gcd(numerator, denominator);
if (denominator.compareTo(BigInteger.ZERO) < 0 ){
this.numerator = numerator.multiply(new BigInteger("-1")).divide(gcd);
} else {
this.numerator = numerator.divide(gcd);
}
this.denominator = denominator.abs().divide(gcd);
}
public static BigInteger gcd(BigInteger n, BigInteger d){
BigInteger n1 = n.abs();
BigInteger n2 = d.abs();
BigInteger gcd = BigInteger.ONE;
for (BigInteger i = BigInteger.ONE; i.compareTo(n1) <= 0 && i.compareTo(n2) <= 0;
i = i.add(BigInteger.ONE) ){
if (n1.remainder(i).equals(BigInteger.ZERO) && n2.remainder(i).equals(BigInteger.ZERO)){
gcd = i;
}
}
return gcd;
}
public BigInteger getNumerator(){
return numerator;
}
public BigInteger getDenominator(){
return denominator;
}
public RationalV8 add(RationalV8 secondRational){
BigInteger n = numerator.multiply(secondRational.getDenominator()).add(
denominator.multiply(secondRational.getNumerator()));
BigInteger d = denominator.multiply(secondRational.getDenominator());
return new RationalV8(n, d);
}
public RationalV8 subtract(RationalV8 secondRational){
BigInteger n = numerator.multiply(secondRational.getDenominator()).subtract(
denominator.multiply(secondRational.getNumerator()));
BigInteger d = denominator.multiply(secondRational.getDenominator());
return new RationalV8(n, d);
}
public RationalV8 multiply(RationalV8 secondRational){
BigInteger n = numerator.multiply(secondRational.getNumerator());
BigInteger d = denominator.multiply(secondRational.getDenominator());
return new RationalV8(n, d);
}
public RationalV8 divide(RationalV8 secondRational){
BigInteger n = numerator.multiply(secondRational.getDenominator());
BigInteger d = denominator.multiply(secondRational.getNumerator());
return new RationalV8(n, d);
}
#Override
public int compareTo(RationalV8 o){
if ( (this.subtract((RationalV8) o)).getNumerator().compareTo(BigInteger.ZERO) > 0){
return 1;
}
else if ( (this.subtract((RationalV8) o)).getNumerator().compareTo(BigInteger.ZERO) < 0){
return -1;
} else {
return 0;
}
}
#Override
public String toString(){
if (denominator.equals(BigInteger.ONE)){
return numerator + " ";
} else {
return numerator + "/" + denominator;
}
}
#Override
public boolean equals(Object param1){
if ((this.subtract( (RationalV8) (param1) )).getNumerator().equals(BigInteger.ZERO) ){
return true;
} else {
return false;
}
}
#Override
public int hashCode(){
return new Double( this.doubleValue() ).hashCode();
}
//#Override
public int intValue(){
return (int)doubleValue();
}
//#Override
public float floatValue(){
return (float)doubleValue();
}
public double doubleValue(){
return numerator.doubleValue() / denominator.doubleValue();
}
public long longValue(){
return (long)doubleValue();
}
}
The running output for this code is:
The sum of the first series is 1/0 = Infinity.
But the output is incorrect because of integer overflow.
Can anyone tell me where is the problem?
I think the line BigInteger n2 = n.abs(); should have been BigInteger n2 = d.abs();. I am not sure this is the only bug.
Related
I'm stuck on a test case.
The question requires to compute a large Fibonacci number in a given period of time.
I have passed 8 cases out of 10 and stuck on 9.
Here is my Code:
import java.util.*;
import java.math.BigInteger;
public class LastNumberofFibo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
BigInteger bi = sc.nextBigInteger();
System.out.println(fib(bi));
}
public static BigInteger fib(BigInteger n) {
BigInteger val=new BigInteger("10");
int k = n.intValue();
BigInteger ans = null;
if(k == 0) {
ans = new BigInteger("0");
} else if(Math.abs(k) <= 2) {
ans = new BigInteger("1");
} else {
BigInteger km1 = new BigInteger("1");
BigInteger km2 = new BigInteger("1");
for(int i = 3; i <= Math.abs(k); ++i) {
ans = km1.add(km2);
km2 = km1;
km1 = ans;
}
}
if(k<0 && k%2==0) { ans = ans.negate(); }
return ans.mod(val);
}
}
After Submitting I get the following Time-out result.
I need help in making my code more efficient.
Feedback :
Failed case #9/10: time limit exceeded
Input:
613455
Your output:
stderr:
(Time used: 3.26/1.50, memory used: 379953152/536870912.)
Please guide me.
Yours Sincerely,
Vidit Shah
I have taken the most easy to implemement suggestions from comments and put it in code.
import java.util.*;
import java.math.BigInteger;
public class LastNumberofFibo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
BigInteger bi = sc.nextBigInteger();
System.out.println(fib(bi));
}
public static BigInteger fib(BigInteger n) {
int m = 10;
BigInteger sixty = new BigInteger("60");
int k = (n.mod(sixty)).intValue();
int ans = 0;
if(k == 0) {
ans = 0;
} else if(Math.abs(k) <= 2) {
ans = 1;
} else {
int km1 = 1;
int km2 = 1;
for(int i = 3; i <= Math.abs(k); ++i) {
ans = (km1 + km2)%m;
km2 = km1;
km1 = ans;
}
}
if(k<0 && k%2==0) { ans = -ans; }
return new BigInteger("" + ans);
}
}
Try that:
public static int fibonacci(int n) {
return (int)((Math.pow((1 + Math.sqrt(5)) / 2, n) - Math.pow((1 - Math.sqrt(5)) / 2, n)) / Math.sqrt(5));
}
import java.util.Collections;
import java.util.Vector;
public class Metaheuristic {
private static int[] DATA;
private static int NUM_CHROMOSOMES ;
private static int MAX_POWER;
private static int MAX_NUMBER;
private static int FITNESS_THRESHOLD;
private static float MUTATE = (float) .05;
private Vector population;
private boolean done = true;
int numRuns = 0;
public void GeneticAlgorithm (int[] data, int target, int n){
NUM_CHROMOSOMES = n;
MAX_POWER = data.length;
MAX_NUMBER = (int) Math.pow(2, MAX_POWER) - 1;
FITNESS_THRESHOLD = target;
DATA = new int[data.length];
DATA = data;
Metaheuristic s = new Metaheuristic();
s.start();
//System.out.println("s");
}
public Metaheuristic(){
generateRandomPopulation();
}
private void generateRandomPopulation(){
System.out.println("***Randomly Generating population with: " + NUM_CHROMOSOMES + " Chromosome(s)***");
population = new Vector();
for(int i = 0; i < NUM_CHROMOSOMES; ++i){
int randomValue = (int) (Math.random()*MAX_NUMBER);
population.add(new Chromosome(randomValue, MAX_POWER));
}
System.out.println("First Population: " + population +"\n");
}
public void start(){
Collections.sort(population);
Chromosome fitess = (Chromosome) population.lastElement();
done = fitess.fitness(DATA, FITNESS_THRESHOLD) >= MAX_POWER? true:false;
if(done){
System.out.println("DONE, solution found: " + fitess);
}
else{
numRuns++;
System.out.println("FITESS: " + fitess + " fitness: " + fitess.fitness(DATA, FITNESS_THRESHOLD ));
generateNewPopulation();
start();
}
}
private void generateNewPopulation(){
System.out.println("***Generating New Population");
Vector temp = new Vector();
for(int i = 0; i < population.size()/2; ++i){
Chromosome p1 = selectParent();
Chromosome p2 = selectParent();
temp.add(cross1(p1, p2));
temp.add(cross2(p1, p2));
}
population.clear();
population.addAll(temp);
System.out.println("New Population: " + population + "\n");
}
private Chromosome selectParent(){
int delta = population.size();
delta = NUM_CHROMOSOMES - NUM_CHROMOSOMES/2;
int num = (int) (Math.random()*10 + 1);
int index;
if(num >= 4){
index = (int) (Math.random()*delta + NUM_CHROMOSOMES/2);
}
else{
index = (int) (Math.random()*delta);
}
return (Chromosome) population.get(index);
}
private Chromosome cross1(Chromosome parent1, Chromosome parent2){
String bitS1 = parent1.getBitString();
String bitS2 = parent2.getBitString();
int length = bitS1.length();
String newBitString = bitS1.substring(0, length/2) + bitS2.substring(length/2, length);
Chromosome offspring = new Chromosome();
offspring.setBitString(newBitString);
if(shouldMutate()){
mutate(offspring);
}
return offspring;
}
private Chromosome cross2(Chromosome parent1, Chromosome parent2){
String bitS1 = parent1.getBitString();
String bitS2 = parent2.getBitString();
int length = bitS1.length();
String newBitString = bitS2.substring(0, length/2) + bitS1.substring(length/2, length);
Chromosome offspring = new Chromosome();
offspring.setBitString(newBitString);
if(shouldMutate()){
mutate(offspring);
}
return offspring;
}
private boolean shouldMutate(){
double num = Math.random();
int number = (int) (num*100);
num = (double) number/100;
return (num <= MUTATE);
}
private void mutate(Chromosome offspring){
String s = offspring.getBitString();
int num = s.length();
int index = (int) (Math.random()*num);
String newBit = flip(s.substring(index, index+1));
String newBitString = s.substring(0, index) + newBit + s.substring(index+1, s.length());
offspring.setBitString(newBitString);
}
private String flip(String s){
return s.equals("0")? "1":"0";
}
public static void main(String[] args) {
double average = 0;
int sum = 0;
for(int i = 0; i < 10; ++i){
Metaheuristic s = new Metaheuristic();
s.start();
sum = sum + s.numRuns;
average = (double) sum / (double)(i+1);
System.out.println("Number of runs: " + s.numRuns);
}
System.out.println("average runs: " + average);
}
}
import java.lang.Comparable;
public class Chromosome implements Comparable{
protected String bitString;
public static int[] DATA;
public int TARGET;
public Chromosome(){
}
public Chromosome(int value, int length){
bitString = convertIntToBitString(value, length);
}
public void setBitString(String s){
bitString = s;
}
public String getBitString(){
return bitString;
}
public int compareTo(Object o) {
Chromosome c = (Chromosome) o;
int num = countOnes(this.bitString) - countOnes(c.getBitString());
return num;
}
public int fitness(int[] data, int target){
DATA = new int[data.length];
System.arraycopy(data, 0, DATA, 0, data.length);
TARGET = target;
return countOnes(bitString);
}
public boolean equals(Object o){
if(o instanceof Chromosome){
Chromosome c = (Chromosome) o;
return c.getBitString().equals(bitString);
}
return false;
}
public int hashCode(){
return bitString.hashCode();
}
public String toString(){
return "Chromosome: " + bitString;
}
public static int countOnes(String bits){
int sum = 0;
for(int i = 0; i < bits.length(); ++ i){
String test = bits.substring(i, i+1);
sum = sum + (DATA[i]*Integer.parseInt(test));
}
return sum;
}
public static String convertIntToBitString(int val, int length){
int reval = val;
StringBuffer bitString = new StringBuffer(length);
for(int i = length-1; i >=0; --i ){
if( reval - (Math.pow(2, i)) >= 0 ){
bitString.append("1");
reval = (int) (reval - Math.pow(2, i));
}
else{
bitString.append("0");
}
}
return bitString.toString();
}
/* public static void main(String[] args){
//System.out.println(convertIntToBitString(2046, 10));
Chromosome c = new Chromosome(1234, 10);
System.out.println(c.fitness());
}*/
}
My fitness function is f(x ) = s · (C − P(x )) + (1 − s) · P(x ) in which C is my target value to reach and P(*x ) = (Sigma) wixi, where wi is the element's set and xi is 0 or 1 (the element is chosen or not). also s is 0 or 1, depends on p(x) value. please help me to write this fitness.
I have just tried it but the program run with errors.
You have several problems in your code, and obviously you didn't debug it. Here are some tips though.
First NUM_CHROMOSOMES is 0, because it's an uninitialized field (of the GeneticAlgorithm which you don't use).
Since NUM_CHROMOSOMES is 0, this for loop is useless:
for (int i = 0; i < NUM_CHROMOSOMES; ++i) {
Then, this line:
int randomValue = (int) (Math.random() * MAX_NUMBER);
Since MAX_NUMBER is never manually initialized (same as NUM_CHROMOSOMES, its value is 0, and so is randomValue.
Anyway, population is empty and since you don't test for emptyness, this line:
Chromosome fitess = (Chromosome) population.lastElement();
... throws an exception, because there is no such thing as a last element in your empty population Vector.
As a side note, StringBuffer, Vector are obsolete classes, and you never need to import Comparable, since it belongs to the java.lang package.
This question already has answers here:
How do I print my Java object without getting "SomeType#2f92e0f4"?
(13 answers)
Closed 7 years ago.
I'm learner of Java.
I'm trying to convert decimal to fraction using BigInteger in Rational class.
If I print the numerator and denominator, right output comes out.
However, when I add, subtract, multiply, and divide, some strange output come out.
For example when I inputs
3.25 -3
The output is
13 4
-3 1
RationalTest#14ae5a5
RationalTest#7f31245a
RationalTest#6d6f6e28
RationalTest#135fbaa4
What is wrong with my code? What is that hashcode?
I couldn't find out in the internet, so I need your help:<
import java.util.Scanner;
import java.math.*;
public class TestTest
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
RationalTest r1 = RationalTest.getFraction(sc.next());
RationalTest r2 = RationalTest.getFraction(sc.next());
//Test if the right numerator and denominator comes out
System.out.println(r1.getNumerator()+" "+r1.getDenominator());
System.out.println(r2.getNumerator()+" "+r2.getDenominator());
System.out.println(r1.add(r2));
System.out.println(r1.subtract(r2));
System.out.println(r1.multiply(r2));
System.out.println(r1.divide(r2));
}
}
class RationalTest extends Number implements Comparable<RationalTest>
{
private static final long serialVersionUID = 1L;
private BigInteger numerator = BigInteger.ZERO;
private BigInteger denominator = BigInteger.ONE;
public RationalTest()
{
this(BigInteger.ZERO, BigInteger.ONE);
}
//Find GCD of numerator and denominator
public RationalTest(BigInteger numerator, BigInteger denominator)
{
BigInteger gcd = gcd(numerator, denominator);
this.numerator = ((denominator.compareTo(BigInteger.ZERO)>0) ? new BigInteger("1"):new BigInteger("-1")).multiply(numerator.divide(gcd));
this.denominator = denominator.abs().divide(gcd);
}
//Converting decimal to fraction
public static RationalTest getFraction(String s)
{
int result=-1;
for(int i=0; i<s.length(); i++)
{
if(s.charAt(i)=='.')
{
result=1;
break;
}
else
result=0;
}
//If result=1, String s is a decimal
if(result==1)
{
double d = Double.parseDouble(s);
long num = (long) Math.floor(d); // Only the int part
double denom = d-num; // Only the decimal part
int digitDec = s.length()-1-s.indexOf('.');
long up = (int) (denom*Math.pow(10, digitDec)); // numerator of denom
long down = (int) Math.pow(10, digitDec); // denominator of denim
return new RationalTest(BigInteger.valueOf(down*num+up), BigInteger.valueOf(down));
}
//If result=0, String s is not a decimal
else
{
return new RationalTest(BigInteger.valueOf(Long.parseLong(s)), BigInteger.ONE);
}
}
private static BigInteger gcd(BigInteger n, BigInteger d)
{
BigInteger n1 = n.abs();
BigInteger n2 = d.abs();
BigInteger gcd = BigInteger.ONE;
for(BigInteger k=BigInteger.ONE; k.compareTo(n1)<=0 && k.compareTo(n2)<=0; k=k.add(BigInteger.ONE))
{
if(n1.mod(k).equals(BigInteger.ZERO) && n2.mod(k).equals(BigInteger.ZERO))
gcd = k;
}
return gcd;
}
public BigInteger getNumerator()
{
return numerator;
}
public BigInteger getDenominator()
{
return denominator;
}
public RationalTest add(RationalTest secondRationalTest)
{
BigInteger n = (numerator.multiply(secondRationalTest.getDenominator())).add(denominator.multiply(secondRationalTest.getNumerator()));
BigInteger d = denominator.multiply(secondRationalTest.getDenominator());
return new RationalTest(n, d);
}
public RationalTest subtract(RationalTest secondRationalTest)
{
BigInteger n = (numerator.multiply(secondRationalTest.getDenominator())).subtract(denominator.multiply(secondRationalTest.getNumerator()));
BigInteger d = denominator.multiply(secondRationalTest.getDenominator());
return new RationalTest(n, d);
}
public RationalTest multiply(RationalTest secondRationalTest)
{
BigInteger n = numerator.multiply(secondRationalTest.getNumerator());
BigInteger d = denominator.multiply(secondRationalTest.getDenominator());
return new RationalTest(n, d);
}
public RationalTest divide(RationalTest secondRationalTest)
{
BigInteger n = numerator.multiply(secondRationalTest.getDenominator());
BigInteger d = denominator.multiply(secondRationalTest.getNumerator());
return new RationalTest(n, d);
}
#Override
public boolean equals(Object other)
{
if((this.subtract((RationalTest)(other))).getNumerator().equals(BigInteger.ZERO))
return true;
else
return false;
}
#Override
public int intValue()
{
return (int)doubleValue();
}
#Override
public float floatValue()
{
return (float)doubleValue();
}
#Override
public double doubleValue()
{
double x = this.getNumerator().doubleValue();
double y = this.getDenominator().doubleValue();
return x/y;
}
#Override
public long longValue()
{
return (long)doubleValue();
}
#Override
public int compareTo(RationalTest o) {
if(this.subtract(o).getNumerator().compareTo(BigInteger.ZERO)>0)
return 1;
else if(this.subtract(o).getNumerator().compareTo(BigInteger.ZERO)<0)
return -1;
else
return 0;
}
}
Oh I found out that I have to return string using toString()..
Thanks for your help!
Hi I'm new to java and am working on a Fraction calculator and I am unable to figure out how to get the calculator to reduce simple fractions and add mixed fractions.
Example:
Reduction: 1/2 + -5/6 = -1/3
Mixed Fractions: 4_15/16 + -3_11/16 = 1_1/4
Edit: For mixed fractions, I tried to subtract the numerator from the denominator for num>den to get the whole and the remainder and return it and print but it's not printing out anything.
import java.util.Scanner;
public class Fraction {
public static void main(String[] args) {
System.out.println("Enter an Expression or quit:");
Scanner input = new Scanner(System.in);
String text = input.nextLine();
while (!text.equals("quit")){
String frac1 = text.substring(0,text.indexOf(" "));
String oper = text.substring((text.indexOf(" "))+1,(text.indexOf(" "))+2);
String frac2 = text.substring((text.indexOf(" "))+3);
int fn1 = num(frac1); //frac1 numerator
int fd1 = den(frac1); //frac1 denominator
int fn2 = num(frac2); //frac2 numerator
int fd2 = den(frac2); //frac2 denominator
if (oper.equals("+")){
int sumfinalnum = add(fn1, fd1, fn2, fd2);
if (fd1 == 1 && fd2 == 1){
System.out.println(sumfinalnum);
}
else if ((fn1 + fn2)==0){
System.out.println("0");
}
else if (fd1 == fd2){
if (sumfinalnum>fd1){
System.out.println(extractWholePart(sumfinalnum,fd1)+"_"+extractNumPart(sumfinalnum,fd1)+"/"+fd1);
}
else{
System.out.println(sumfinalnum+"/"+fd1);
}
}
else if (!(fd1 == fd2)){
System.out.println(sumfinalnum+"/"+(fd1*fd2));
}
System.out.println("Enter an Expression or quit:");
text = input.nextLine();
}
}
}
public static int num(String input){
if (input.contains("_")){ //mixed to improper
String a = input.substring(0,input.indexOf("_"));
String b = input.substring((input.indexOf("_"))+1,input.indexOf("/"));
String c = input.substring((input.indexOf("/"))+1);
int a1 = Integer.parseInt(a);
int b1 = Integer.parseInt(b);
int c1 = Integer.parseInt(c);
int d = a1*c1;
int e = d+b1;
return e;
}
else if (!input.contains("/")){
int input1 = Integer.parseInt(input);
return input1;
}
else {
String strnum1 = input.substring(0,input.indexOf("/"));
int num1 = Integer.parseInt(strnum1);
return num1;
}
}
public static int den(String input){
if(!input.contains("/")) { //whole
return 1;
}
String strnum2 = input.substring((input.indexOf("/"))+1);
int num2 = Integer.parseInt(strnum2);
return num2;
}
public static int add(int fn1,int fd1,int fn2,int fd2){
if (fd1 == fd2){ //matching denominator
int numadd = fn1 + fn2;
return numadd;
}
else if (fd1 == 1 && fd2 == 1){ //whole numbers no denom
int sum = fn1 + fn2;
return sum;
}
else if (!(fd1 == fd2)){ //different denominator***
int dencomadd = fd1*fd2;
int gcd1 = dencomadd/fd1;
int gcd2 = dencomadd/fd2;
int comf1num = fn1*gcd1;
int comf2num = fn2*gcd2;
int total = comf1num+comf2num;
return total;
}
else{
return 0;
}
}
public static int extractWholePart(int finalnum, int finalden){
int whole = 0;
while (finalnum > finalden){
whole++;
}
return whole;
}
public static int extractNumPart(int finalnum, int finalden){
while (finalnum > finalden){
finalnum -= finalden;
}
return finalnum;
}
}
Let's start with - It's java, don't be afraid to use bigger variable names. fn1 could very well be called fraction1Numerator.
Next, have a single method to do what it's designed to do. Having an add method that needs four else-ifs in main is not a really good idea.
Creating an object Fraction that would have member variables numerator and denominator would allow your add function to return the entire answer. After all you have the code to add mixed fractions that looks good.
class Fraction{
public int whole;
public int numerator;
public int denominator;
}
I also added "whole" to indicate whole part after simplification. add function would than have signature
public static Fraction add(Fraction fraction1, Fraction fraction2) ...
Extracting whole numbers is simple - subtract denominator from numerator until you can't do that anymore.
public void extractWholePart(Fraction fraction){
int whole = 0;
while (fraction.numerator > fraction.denominator){
whole++;
fraction.numerator -= fraction.denominator;
}
fraction.whole = whole;
}
simplification on the other hand is just dividing both nominator and denominator by the greatest common divisor - algorythm for calculating that is easily findable on the internet.
Try something like this
float mixedToDecimal(String data)
// data would be like this "1 5/8";
String[] parts = data.split(" ");
if(!(parts.lenght > 0)) // this mean that if data is NOT mixedfraction then just return -1
return -1;
float value = Integer.parseInt(parts[0]);
if (parts.length > 1) {
// has fractional part
parts = parts[1].split("/");
float numerator = Integer.parseInt(parts[0]);
float denominator = Integer.parseInt(parts[1]);
value += numerator / denominator;
}
// value contains 1.625
return value;
I get stack on my error of point multiplication using standard projective coordinates. I don't know what i missed but the multiplied points do not lie on the curve and some times it outputs something like Arithmetic Exception: integer is not invertible.
public class ECPointArthimetic {
EllipticCurve ec;
private BigInteger x;
private BigInteger y;
private BigInteger z;
private BigInteger zinv;
private BigInteger one = BigInteger.ONE;
private BigInteger zero = BigInteger.ZERO;
private boolean infinity;
public ECPointArthimetic(EllipticCurve ec, BigInteger x, BigInteger y, BigInteger z) {
this.ec = ec;
this.x = x;
this.y = y;
// Projective coordinates: either zinv == null or z * zinv == 1
// z and zinv are just BigIntegers, not fieldElements
if (z == null) {
this.z = BigInteger.ONE;
} else {
this.z = z;
}
this.zinv = null;
infinity = false;
//TODO: compression flag
}
public BigInteger getX() {
if (this.zinv == null) {
this.zinv = this.z.modInverse(this.ec.getP());
}
return this.x.multiply(this.zinv).mod(this.ec.getP());
}
public BigInteger getY() {
if (this.zinv == null) {
this.zinv = this.z.modInverse(this.ec.getP());
}
return this.y.multiply(this.zinv).mod(this.ec.getP());
}
public boolean pointEquals(ECPointArthimetic other) {
if (other == this) {
return true;
}
if (this.isInfinity()) {
return other.isInfinity();
}
if (other.isInfinity()) {
return this.isInfinity();
}
BigInteger u, v;
// u = Y2 * Z1 - Y1 * Z2
u = other.y.multiply(this.z).subtract(this.y.multiply(other.z)).mod(this.ec.getP());
if (!u.equals(BigInteger.ZERO)) {
return false;
}
// v = X2 * Z1 - X1 * Z2
v = other.x.multiply(this.z).subtract(this.x.multiply(other.z)).mod(this.ec.getP());
return v.equals(BigInteger.ZERO);
}
public boolean isInfinity() {
if ((this.x == zero) && (this.y == zero)) {
return true;
}
return this.z.equals(BigInteger.ZERO) && !this.y.equals(BigInteger.ZERO);
}
public ECPointArthimetic negate() {
return new ECPointArthimetic(this.ec, this.x, this.y.negate(), this.z);
}
public ECPointArthimetic add(ECPointArthimetic b) {
if (this.isInfinity()) {
return b;
}
if (b.isInfinity()) {
return this;
}
ECPointArthimetic R = new ECPointArthimetic(this.ec, zero, zero, null);
// u = Y2 * Z1 - Y1 * Z2
BigInteger u = b.y.multiply(this.z).
subtract(this.y.multiply(b.z)).mod(this.ec.getP());
// v = X2 * Z1 - X1 * Z2
BigInteger v = b.x.multiply(this.z).
subtract(this.x.multiply(b.z)).mod(this.ec.getP());
if (BigInteger.ZERO.equals(v)) {
if (BigInteger.ZERO.equals(u)) {
return this.twice(); // this == b, so double
}
infinity = true; // this = -b, so infinity
return R;
}
BigInteger THREE = new BigInteger("3");
BigInteger x1 = this.x;
BigInteger y1 = this.y;
BigInteger x2 = b.x;
BigInteger y2 = b.y;
BigInteger v2 = v.pow(2);
BigInteger v3 = v2.multiply(v);
BigInteger x1v2 = x1.multiply(v2);
BigInteger zu2 = u.pow(2).multiply(this.z);
// x3 = v * (z2 * (z1 * u^2 - 2 * x1 * v^2) - v^3)
BigInteger x3 = zu2.subtract(x1v2.shiftLeft(1)).multiply(b.z).
subtract(v3).multiply(v).mod(this.ec.getP());
// y3 = z2 * (3 * x1 * u * v^2 - y1 * v^3 - z1 * u^3) + u * v^3
BigInteger y3 = x1v2.multiply(THREE).multiply(u).
subtract(y1.multiply(v3)).subtract(zu2.multiply(u)).
multiply(b.z).add(u.multiply(v3)).mod(this.ec.getP());
// z3 = v^3 * z1 * z2
BigInteger z3 = v3.multiply(this.z).multiply(b.z).mod(this.ec.getP());
return new ECPointArthimetic(this.ec, x3, y3, z3);
}
public ECPointArthimetic twice() {
if (this.isInfinity()) {
return this;
}
ECPointArthimetic R = new ECPointArthimetic(this.ec, zero, zero, null);
if (this.y.signum() == 0) {
infinity = true;
return R;
}
BigInteger THREE = new BigInteger("3");
BigInteger x1 = this.x;
BigInteger y1 = this.y;
BigInteger y1z1 = y1.multiply(this.z);
BigInteger y1sqz1 = y1z1.multiply(y1).mod(this.ec.getP());
BigInteger a = this.ec.getA();
// w = 3 * x1^2 + a * z1^2
BigInteger w = x1.pow(2).multiply(THREE);
if (!BigInteger.ZERO.equals(a)) {
w = w.add(this.z.pow(2).multiply(a));
}
w = w.mod(this.ec.getP());
// x3 = 2 * y1 * z1 * (w^2 - 8 * x1 * y1^2 * z1)
BigInteger x3 = w.pow(2).subtract(x1.shiftLeft(3).multiply(y1sqz1)).
shiftLeft(1).multiply(y1z1).mod(this.ec.getP());
// y3 = 4 * y1^2 * z1 * (3 * w * x1 - 2 * y1^2 * z1) - w^3
BigInteger y3 = (w.multiply(THREE).multiply(x1).subtract(y1sqz1.shiftLeft(1))).
shiftLeft(2).multiply(y1sqz1).subtract(w.pow(2).multiply(w)).mod(this.ec.getP());
// z3 = 8 * (y1 * z1)^3
BigInteger z3 = y1z1.pow(2).multiply(y1z1).shiftLeft(3).mod(this.ec.getP());
return new ECPointArthimetic(this.ec, x3, y3, z3);
}
public ECPointArthimetic multiply(BigInteger k) {
if (this.isInfinity()) {
return this;
}
ECPointArthimetic R = new ECPointArthimetic(this.ec, zero, zero, null);
if (k.signum() == 0) {
infinity = true;
return R;
}
BigInteger e = k;
BigInteger h = e.multiply(new BigInteger("3"));
ECPointArthimetic neg = this.negate();
R = this;
int i;
for (i = h.bitLength() - 2; i > 0; --i) {
R = R.twice();
boolean hBit = h.testBit(i);
boolean eBit = e.testBit(i);
if (hBit != eBit) {
R = R.add(hBit ? this : neg);
}
}
return R;
}
public ECPointArthimetic implShamirsTrick( BigInteger k,
ECPointArthimetic Q, BigInteger l){
int m = Math.max(k.bitLength(), l.bitLength());
ECPointArthimetic Z = this.add(Q);
ECPointArthimetic R = new ECPointArthimetic(ec,zero,zero,null);
for (int i = m - 1; i >= 0; --i){
R = R.twice();
if (k.testBit(i)){
if (l.testBit(i)){
R = R.add(Z);
}else{
R = R.add(this);
}
}else{
if (l.testBit(i)){
R = R.add(Q);
}
}
}
return R;
}
}
Here are the curves I used :
package NISTCurves;
import ecc.*;
import java.math.BigInteger;
public class P192 implements ECDomainParameters {
String p192X = "188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012";
String p192Y = "07192b95ffc8da78631011ed6b24cdd573f977a11e794811";
String p192B = "64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1";
String p192P = "6277101735386680763835789423207666416083908700390324961279";
String p192Order = "6277101735386680763835789423176059013767194773182842284081";
String p192A = "-3";
BigInteger p = new BigInteger(p192P, 16);
EllipticCurve ec =
new EllipticCurve(p,
new BigInteger(p192A).mod(p),
new BigInteger(p192B, 16));
ECPointArthimetic G = new ECPointArthimetic(ec, new BigInteger(p192X,16),
new BigInteger(p192Y,16),null);
BigInteger order = new BigInteger(p192Order, 16);
#Override
public BigInteger getP() {
return p;
}
#Override
public EllipticCurve getECCurve() {
return ec;
}
#Override
public BigInteger getOrder() {
return order;
}
#Override
public ECPointArthimetic getGenerator() {
return G;
}
}
Specification of Elliptic curve domain parameters
package NISTCurves;
import ecc.ECPointArthimetic;
import ecc.EllipticCurve;
import java.math.BigInteger;
public interface ECDomainParameters {
public BigInteger getP();
public ECPointArthimetic getGenerator();
public EllipticCurve getECCurve();
public BigInteger getOrder();
}
Elliptic curve digital signature Algorithm implementation is here.
In this code there is main function so use this to test Exception.
package ecc;
import NISTCurves.ECDomainParameters;
import NISTCurves.P192;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
*
* #author Gere
*/
public class ECDSA {
private BigInteger r, s;
ECDomainParameters param;
private PrivateKey prvKey;
private PublicKey pubKey;
BigInteger zero = BigInteger.ZERO;
private BigInteger one = BigInteger.ONE;
private MessageDigest sha;
public ECDSA() {
try {
sha = MessageDigest.getInstance("SHA-512");
} catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
}
}
public void initSign(PrivateKey prvKey) {
this.prvKey = prvKey;
param = prvKey.getParam();
}
public void initVerify(PublicKey pubKey) {
this.pubKey = pubKey;
param = pubKey.getParam();
}
public void update(byte[] byteMsg) {
sha.update(byteMsg);
}
public byte[] sign() throws FileNotFoundException, IOException {
BigInteger c = new BigInteger(
param.getP().bitLength() + 64, Rand.sr);
BigInteger k = c.mod(param.getOrder().subtract(one)).add(one);
while (!(k.gcd(param.getOrder()).compareTo(one) == 0)) {
c = new BigInteger(param.getP().bitLength() + 64, Rand.sr);
k = c.mod(param.getOrder().subtract(one)).add(one);
}
BigInteger kinv = k.modInverse(param.getOrder());
ECPointArthimetic p = param.getGenerator().multiply(k);
if (p.getX().equals(zero)) {
return sign();
}
BigInteger hash = new BigInteger(sha.digest());
BigInteger r = p.getX().mod(param.getOrder());
BigInteger s = (kinv.multiply((hash.add((prvKey.getPrivateKey()
.multiply(r)))))).mod(param.getOrder());
if (s.compareTo(zero) == 0) {
return sign();
}
System.out.println("r at sign: " + r);
System.out.println("s at sign: " + s);
byte[] rArr = toUnsignedByteArray(r);
byte[] sArr = toUnsignedByteArray(s);
int nLength = (param.getOrder().bitLength() + 7) / 8;
byte[] res = new byte[2 * nLength];
System.arraycopy(rArr, 0, res, nLength - rArr.length, rArr.length);
System.arraycopy(sArr, 0, res, 2 * nLength - sArr.length,
sArr.length);
return res;
}
public boolean verify(byte[] res) {
int nLength = (param.getOrder().bitLength() + 7) / 8;
byte[] rArr = new byte[nLength];
System.arraycopy(res, 0, rArr, 0, nLength);
r = new BigInteger(rArr);
byte[] sArr = new byte[nLength];
System.arraycopy(res, nLength, sArr, 0, nLength);
s = new BigInteger(sArr);
System.out.println("r at verify: " + r);
System.out.println("s at verify: " + s);
BigInteger w, u1, u2, v;
// r in the range [1,n-1]
if (r.compareTo(one) < 0 || r.compareTo(param.getOrder()) >= 0) {
return false;
}
// s in the range [1,n-1]
if (s.compareTo(one) < 0 || s.compareTo(param.getOrder()) >= 0) {
return false;
}
w = s.modInverse(param.getOrder());
BigInteger hash = new BigInteger(sha.digest());
u1 = hash.multiply(w);
u2 = r.multiply(w);
ECPointArthimetic G = param.getGenerator();
ECPointArthimetic Q = pubKey.getPublicKey();
// u1G + u2Q
ECPointArthimetic temp = G.implShamirsTrick(u1, Q, u2);
v = temp.getX();
v = v.mod(param.getOrder());
return v.equals(r);
}
byte[] toUnsignedByteArray(BigInteger bi) {
byte[] ba = bi.toByteArray();
if (ba[0] != 0) {
return ba;
} else {
byte[] ba2 = new byte[ba.length - 1];
System.arraycopy(ba, 1, ba2, 0, ba.length - 1);
return ba2;
}
}
public static void main(String[] args) {
byte[] msg = "Hello".getBytes();
byte[] sig = null;
ECDomainParameters param = new P192();
PrivateKey prvObj = new PrivateKey(param);
PublicKey pubObj = new PublicKey(prvObj);
ECDSA ecdsa = new ECDSA();
ecdsa.initSign(prvObj);
ecdsa.update(msg);
try {
sig = ecdsa.sign();
} catch (FileNotFoundException ex) {
System.out.println(ex.getMessage());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
ecdsa.initVerify(pubObj);
ecdsa.update(msg);
if (ecdsa.verify(sig)) {
System.out.println("valid");
} else {
System.out.println("invalid");
}
}
}
Here PrivateKey class
package ecc;
import NISTCurves.ECDomainParameters;
import java.math.BigInteger;
import java.security.SecureRandom;
/**
*
* #author Gere
*/
public class PrivateKey {
private BigInteger d;
private ECDomainParameters param;
private BigInteger one = BigInteger.ONE;
private BigInteger zero;
private PublicKey pubKey;
public PrivateKey(ECDomainParameters param) {
this.param = param;
BigInteger c = new BigInteger(param.getOrder().bitLength() + 64,
new SecureRandom());
BigInteger n1 = param.getOrder().subtract(one);
d = c.mod(n1).add(one);
pubKey = new PublicKey(this);
}
public BigInteger getPrivateKey() {
return d;
}
public ECDomainParameters getParam() {
return param;
}
}
PublicKey class
package ecc;
import NISTCurves.ECDomainParameters;
/**
*
* #author Gere
*/
public class PublicKey {
private ECDomainParameters param;
private ECPointArthimetic Q;
public PublicKey(PrivateKey privObj) {
param = privObj.getParam();
Q = param.getGenerator().multiply(privObj.getPrivateKey());
}
public ECDomainParameters getParam() {
return param;
}
public ECPointArthimetic getPublicKey() {
return Q;
}
}
Elliptic curve
package ecc;
import java.math.BigInteger;
/**
*
* #author Gere
*/
public class EllipticCurve {
private BigInteger a;
private BigInteger b;
private BigInteger p;
public EllipticCurve(BigInteger a, BigInteger b, BigInteger p) {
this.a = a;
this.b = b;
this.p = p;
}
public BigInteger getA() {
return a;
}
public BigInteger getB() {
return b;
}
public BigInteger getP() {
return p;
}
}
Rand class
package ecc;
import java.security.SecureRandom;
/**
*
* #author Gere
*/
public class Rand {
public static final SecureRandom sr = new SecureRandom();
}
Elliptic Curves interface
package ecc;
import java.math.BigInteger;
public interface ECConstants{
public static final BigInteger zero = BigInteger.valueOf(0);
public static final BigInteger one = BigInteger.valueOf(1);
public static final BigInteger two = BigInteger.valueOf(2);
public static final BigInteger three = BigInteger.valueOf(3);
public static final BigInteger four= BigInteger.valueOf(4);
}
The most important errors are in NISTCurves.P192: p and the order are in base-10, not in base-16. Also, when you construct the EllipticCurve-object, you provide the parameters in the wrong order. Your method requires (a, b, p), but you call it with (p, a, b) (so my guess about p not being prime was correct).
Another problem is in your verify-method, when you unwrap r and s. Since they are in unsigned format, you should use new BigInteger(1, rArr) instead of the normal constructor.
With those changes your code works for me (I can validate the signatures - I have not verified the correctness of the implementation).
(Old answer below:)
Since you have not given us the code that matches the stacktrace, this will merely be a guess:
During elliptic curve addition (with a curve over a prime field), you should only be calling BigInteger.modInverse() with the prime p (the order of the prime field) as the modulus.
The most probable way for this to fail sporadically with "BigInteger not invertible" is if p is not actually a prime.
Where are you getting p from? Try inserting
if(!ec.getP().isProbablePrime(100)) throw new RuntimeException("P is not a prime");
somewhere.
From the JDK java code for BigInteger:
// Base and modulus are even, throw exception
if (isEven())
throw new ArithmeticException("BigInteger not invertible.");
It seems that for the modInverse() method, the BigInteger may not be an even number.