I have trouble with this equation: E * cotangent((q * E)/(k * t)) = nkT/q.
I'm looking for the values of E for the equality can be achieved
knowing that: q and k are constants, t and n are variables.
For that I tried this code but apparently is failed:
public class Equation {
public static double q = 1.6E-19;
public static double k = 1.38E-23;
//double y = E * 1/Math.tan(E*q/k*t);
//DecimalFormat df = new DecimalFormat("#.#####");
public static double[] nktq = new double[]{0.02857,0.02674,0.03118,0.02829,0.02976,0.02898,0.03001,0.02953,0.032};
public static double[] t = new double[]{80,100,150,200,250,280,300,320,350};
public static double[] n = new double[]{4.14,3.1,2.41,1.64,1.38,1.20,1.16,1.07,1.06};
private static DecimalFormat df2 = new DecimalFormat(".##");
public static double genE(){
double start = 0;
double end = 30;
double random = new Random().nextDouble();
// DecimalFormat df = new DecimalFormat("#.##");
// df.setRoundingMode(RoundingMode.FLOOR);
double E = start + (random * (end - start));
//double E = new Double(df.format(result));
System.out.println(df2.format(E));
return E;
}
public static void main(String[] args) {
//double y = E * 1/Math.tan(E*q/k*t);
//DecimalFormat df = new DecimalFormat("#.#####")
double E = 0;
while ( Math.round(E * 1/Math.tan((q * E)/(k * t[0]))*100000)!= nktq[0]){
genE();
}
}
}
Any help is appreciated!
You create a new Random instance for each value. That's wrong.
Here's what I'd recommend you try:
public class Equation {
private Random random;
public Equation() { this(null); }
public Equation(Long seed) {
this.random = (seed == null) ? new Random() : new Random(seed.longValue());
}
public double nextConst() { return this.random.nextDouble(); }
public double nextConst(double start, double end) {
return start + (end-start)*this.random.nextDouble();
}
// Add the rest of your stuff here.
}
Related
I declared the private Complex variable 'root' in my class.
I set the value of root to a Complex number inside the void method 'iterate'
I wish to print the new value of 'root' (line 60) but when I try, it prints as null. So I don't think it is calling the correct 'root'.
My code:
class Newton {
public static final int MAXITER = 20;
public static final double TOL = 1.0e-10;
private Polynomial f; //Polynomial
private Polynomial fp; //Derivative of the polynomial
private Complex root;
private int numIterations;
private int err;
//Basic constructor. Calculate and set fp in this method.
public Newton(Polynomial p) {
this.f = p;
this.fp = p.derivative();
}
// Newton-Rapshon method
public void iterate(Complex z0) {
Complex[] z = new Complex[MAXITER];
z[0] = z0;
for(int i = 0 ; i<MAXITER ; i++){
if(fp.evaluate(z[i]).abs() <= TOL){
this.err = -1;
return;
}
z[i+1] = z[i].add((f.evaluate(z[i])).divide(fp.evaluate(z[i])));
if(f.evaluate(z[i]).abs() != TOL){
this.err = -2;
return;
} if (f.evaluate(z[i]).abs() <= TOL){
this.err = 0;
this.root = z[i];
this.numIterations = i;
return;
}
}}
// Tester function.
public static void main(String[] args) {
// Basic tester: find a root of f(z) = z^3-1 from the starting point
// z_0 = 1+i.
Complex[] coeff = new Complex[] { new Complex(-1.0,0.0), new Complex(),
new Complex(), new Complex(1.0,0.0) };
Polynomial p = new Polynomial(coeff);
Newton n = new Newton(p);
Complex z0 = new Complex(1.0,1.0);
n.iterate(z0);
System.out.println(n.root);
}}
You need to create a getter for root in your Newton class since it is a private field.
class Newton {
public static final int MAXITER = 20;
public static final double TOL = 1.0e-10;
private Polynomial f; //Polynomial
private Polynomial fp; //Derivative of the polynomial
private Complex root;
private int numIterations;
private int err;
//Basic constructor. Calculate and set fp in this method.
public Newton(Polynomial p) {
this.f = p;
this.fp = p.derivative();
}
public Complex getRoot(){
return this.root;
}
}
You can then use the getter instead of trying to access n.root (i.e., using newtonObj.getRoot() instead of newtonObj.root):
// Tester function.
public static void main(String[] args) {
// Basic tester: find a root of f(z) = z^3-1 from the starting point
// z_0 = 1+i.
Complex[] coeff = new Complex[] { new Complex(-1.0,0.0), new Complex(),
new Complex(), new Complex(1.0,0.0) };
Polynomial p = new Polynomial(coeff);
Newton n = new Newton(p);
Complex z0 = new Complex(1.0,1.0);
n.iterate(z0);
System.out.println(n.getRoot());
}
I am practicing some Java and one of the applications I am writing asks to output the world population in the next 75 years.
I am using the population growth model. My issue is that my application outputs 'Infinity' in the column where the estimated population should be output.
This is my code:
import java.util.Calendar;
import java.util.regex.Matcher;
public class WorldPopulationGrowth {
public static void main(String[] args) {
double currentWorldPopulation = 7.4e9;
double worldPopulationGrowthRate = 1.13;
double anticipatedWorldPopulation;
int initialYear = Calendar.getInstance().get(Calendar.YEAR);
System.out.println("Year\tAnticipated World Population (in billions)\tPopulation " +
"increase since last year");
System.out.println(String.format("%d\t%.1e\t\t\t\t\t\t\t\t\t\t\tNA", initialYear, currentWorldPopulation) );
for(int i=1; i < 76; i++){
int year = initialYear + i;
double growthExponential = worldPopulationGrowthRate*year*1.0;
anticipatedWorldPopulation = currentWorldPopulation * Math.pow(Math.E, growthExponential);
System.out.println(String.format("%d\t%.1e\t\t\t\t\t\t\t\t\t\t\t", year, anticipatedWorldPopulation));
currentWorldPopulation = anticipatedWorldPopulation;
}
}
}
Let's take a careful look at the first iteration of your code, as if we were debugging it (Make sure you try to do this in the future!)
currentWorldPopulation = 7.4e9
worldPopulationGrowthRate is 1.13
initialYear is 2016
your loop begins, i is 1
year is set to 2017
growthExponential is set to 1.13 * 2017 = 2279.21 (this is the start of your problem)
anticipatedWorldPopulation is set to 7.4e9 * e^2279.21
this is roughly 7.4e9 * 7.05e989... KABOOM
Revisit your calculations, and step through your application (ideally in a debugger) to see your problems.
#Krease found your problem.
I recoded it. Once you fix the issue he found it's fine. I used JDK 8 lambdas and gave you both percentage and exponential growth models. The code prints both for comparison:
import java.util.function.DoubleFunction;
/**
* Simplistic population growth model
* #link https://stackoverflow.com/questions/38805318/getting-infinity-output-instead-of-actual-numbers/38805409?noredirect=1#comment64979614_38805409
*/
public class WorldPopulationGrowth {
public static void main(String[] args) {
double currentWorldPopulation = 7.4e9;
double worldPopulationGrowthRate = 1.13;
int numYears = 76;
int startYear = 1976;
double populationExponential = currentWorldPopulation;
ExponentialGrowthModel modelExpGrowth = new ExponentialGrowthModel(worldPopulationGrowthRate);
double populationPercentage = currentWorldPopulation;
PercentageGrowthModel modelPercentGrowth = new PercentageGrowthModel(worldPopulationGrowthRate);
System.out.println(String.format("%10s %20.3e %20.3e", startYear, currentWorldPopulation, currentWorldPopulation));
for (int i = 1; i < numYears; ++i) {
populationExponential = modelExpGrowth.apply(populationExponential);
populationPercentage = modelPercentGrowth.apply(populationPercentage);
System.out.println(String.format("%10s %20.3e %20.3e", startYear+i, populationExponential, populationPercentage));
}
}
}
class ExponentialGrowthModel implements DoubleFunction<Double> {
private double exponent;
ExponentialGrowthModel(double exponent) {
this.exponent = exponent;
}
private double getExponent() {
return exponent;
}
public void setExponent(double exponent) {
this.exponent = exponent;
}
#Override
public Double apply(double value) {
return value*Math.exp(this.getExponent());
}
}
class PercentageGrowthModel implements DoubleFunction<Double> {
private double percentageIncrease;
PercentageGrowthModel(double percentageIncrease) {
this.percentageIncrease = percentageIncrease;
}
private double getPercentageIncrease() {
return percentageIncrease;
}
public void setPercentageIncrease(double percentageIncrease) {
this.percentageIncrease = percentageIncrease;
}
#Override
public Double apply(double value) {
return value*(this.getPercentageIncrease());
}
}
My problem is that for the getTime(); command, you need all of the speed, handling, xcord, ycord, and the terrainDifficultry variables to have an answer, yet I can only call getTime(); from the mb1 class. Basically, I keep getting 0.0 when i get to System.out getTime() and I don't know how to fix it.
import java.util.Scanner;
public class Main_MoonRace {
public static void main(String[] args)
{
Scanner keyboard = new Scanner (System.in);
System.out.println("Enter the speed of the moonbuggy as an integer.");
int s = keyboard.nextInt();
System.out.println("Enter the handling of the moonbuggy (between 0-0.9)");
double h = keyboard.nextDouble();
moonbuggy mb1 = new moonbuggy(s,h);
System.out.println("Enter the x-coordinate of where the moonbuggy will be headed to as an integer.");
int xcord = keyboard.nextInt();
System.out.println("Enter the y-coordinate of where the moonbuggy will be headed to as an integer.");
int ycord = keyboard.nextInt();
System.out.println("Enter the difficulty of the terrain that the moonbuggy will be experiencing (integer from 1-10).");
int terrainDifficulty = keyboard.nextInt();
MoonLocation mL1 = new MoonLocation(xcord,ycord,terrainDifficulty);
System.out.println(mb1.getTime());
}
}
moonbuggy.java
public class moonbuggy {
private int speed = 1;
private double handling = 0;
moonbuggy(){
return;
}
moonbuggy(int s, double h){
speed = s;
handling = h;
return;
}
public void setSpeed (int s){
speed = s;
}
public void setHandling (double h){
handling = h;
}
public int getSpeed(){
return speed;
}
public double getHandling(){
return handling;
}
MoonLocation obj1 = new MoonLocation();
public double getTime(){
double time = (((obj1.getdistance())/(getSpeed()))*(obj1.getTerrain())*(1-(getHandling())));
return time;
}
}
MoonLocation.java
public class MoonLocation {
private int x = 0;
private int y = 0;
private int terrain = 1;
MoonLocation(){
return;
}
MoonLocation(int xcord, int ycord, int terrainDifficulty){
x= xcord;
y = ycord;
terrain = terrainDifficulty;
return;
}
public void setX (int xcord){
x = xcord;
}
public void setY (int ycord){
y = ycord;
}
public void setTerrain (int terrainDifficulty){
terrain = terrainDifficulty;
}
public int getX () {
return x;
}
public int getY () {
return y;
}
public int getTerrain () {
return terrain;
}
public double getdistance () {
double distance = Math.sqrt((Math.pow(x,2))+(Math.pow(y,2)));
return distance;
}
}
Have a look at this part of code in your moonbuggy class (note that by convention a class should always start with uppercase in java).
MoonLocation obj1 = new MoonLocation();
public double getTime(){
double time = (((obj1.getdistance())/(getSpeed()))*(obj1.getTerrain())*(1-(getHandling())));
return time;
}
You instanciate a MoonLocation without any parameters, then you access it in your getTime method. This explain why you always get 0.0 as result when calling getTime.
Now modify your getTime method to
public double getTime(MoonLocation location){
return (((location.getdistance())/(getSpeed()))*(location.getTerrain())*(1-(getHandling())));
}
Notice that I removed the time variable as it is completly useless there.
And change in your main
MoonLocation mL1 = new MoonLocation(xcord,ycord,terrainDifficulty);
System.out.println(mb1.getTime());
To
MoonLocation mL1 = new MoonLocation(xcord,ycord,terrainDifficulty);
System.out.println(mb1.getTime(mL1));
Also, please remove the unused MoonLocation obj1 = new MoonLocation() in your moonbuggy class.
The Problem lies with your code. In the first place, you are creating an object of MoonLocation in Main_MoonRace class under main() method as :
MoonLocation mL1 = new MoonLocation(xcord,ycord,terrainDifficulty);
Here, an object of MoonLocation is created and initialized with xcord, ycord, and terrainDifficulty values.
Now, in your MoonBuggy class, again you are creating an object of MoonLocation as :
MoonLocation obj1 = new MoonLocation();
Here, only an empty object of MoonLocation class is created.
Now, when you call :
obj1.getDistance(); It will return 0 only.
Below is the corrected code for MoonBuggy class.
public class Moonbuggy {
private int speed = 1;
private double handling = 0;
Moonbuggy(){}
Moonbuggy(int s, double h){
speed = s;
handling = h;
}
public void setSpeed (int s){
speed = s;
}
public void setHandling (double h){
handling = h;
}
public int getSpeed(){
return speed;
}
public double getHandling(){
return handling;
}
private MoonLocation obj1;
public MoonLocation getObj1() {
return obj1;
}
public void setObj1(MoonLocation obj1) {
this.obj1 = obj1;
}
public double getTime(){
double time = (((obj1.getdistance())/(getSpeed()))*(obj1.getTerrain())*(1-(getHandling())));
return time;
}
}
and an addtion in the main() method :
MoonLocation mL1 = new MoonLocation(xcord,ycord,terrainDifficulty);
mb1.setObj1(mL1); // set the MoonLocation object
System.out.println(mb1.getTime());
Now , you will get the proper output
I am trying to run a class that performs calculations from data obtained from a random variable generator class. What I want is that 3 random variables be generated at any given time, then all calculation in that class be performed without another set of random variables be generated. Once all calculations have been performed then a new set of random variables can be generated. The Computation class is as shown below :
public class Computation {
public int meltTemp;
//public void mTemp;
public int mouldTemp;
public int setTemp;
public int Q;
public int volume;
public double Cp;
public int actualMouldTemp;
public double dT;
public int AMT ;//= Math.abs(dT);
public double mTemp;
public Hashtable catalogue1;
protected void setup() {
//create Hashtable
catalogue1 = new Hashtable();
}
public double getAnswer() {
int rand1[] = new int[3];
int input [] = new int [2];
ControlGUI par = new ControlGUI ();
//input = ControlGUI.getArray();
//catalogue am = new catalogue();
RandomVariableGenerator var = new RandomVariableGenerator();
rand1 = RandomVariableGenerator.getRand();
//int rand[] = Arrays.copyOf(rand1, rand1.length);
meltTemp = 245;
System.out.println("Melt Temp is : "+ meltTemp);
actualMouldTemp = (int) ((0 - 51.4)+(0.302 * meltTemp) +(1.64 * rand1[0])+(0.201 * rand1[1]));
System.out.println("The actual mould temperature is :" +actualMouldTemp + " Degrees celcius" );
return actualMouldTemp;
}
public int getDiff(){
Computation amg = new Computation();
double result[] = new double [4]; {
setTemp = 55;
dT = (actualMouldTemp - setTemp);
AMT = (int) Math.abs(dT);
System.out.println("The temperature difference is : "+ AMT);
return AMT;
}
}
The next method to try and use the generated variables is getHeatingTime1() which needs rand1[2] for the tank volume:
public double getHeatingTime1(){
Computation jose = new Computation();
int [] Results = new int [4];
Results [0] = AMT;
//Results [] = Computation.class;
Q = 3; //heating in kW
Cp = 4.2; //Specific heat capacity of water
volume = 6;
//AMT =
System.out.println("AMT IS "+ Results [0]);
long HT1 = (long) ((volume*Cp*Results [0])/Q);
return HT1;
}
public double getHeatingTime2(){
int Results [] = new int [4] ;
Computation cr7 = new Computation();
//double dT = cr7.getDiff();
Q = 9; //heating in kW
Cp = 4.2; //Specific heat capacity of water
volume = 6;
//AMT = 7;
System.out.println("AMT IS "+ Results [1]);
long HT2 = (long) ((volume*Cp*Results [1])/Q);
return HT2;
}
public double getHeatingTime3(){
int Results [] = new int [4];
//double AMT = getDiff();
Computation jt = new Computation();
//double dT = jt.getDiff();
// AMT = 7;
Q = 18; //heating in kW
Cp = 4.2; //Specific heat capacity of water
volume = 6;
System.out.println("AMT IS "+ Results [1]);
long HT3 = (long) ((volume*Cp*Results [1])/Q);
return HT3;
}
public double getCoolingTime(){
// double CT = 0;
Computation nvh = new Computation();
int rand1[] = new int[3];
int rand[] = Arrays.copyOf(rand1, rand1.length);
//RandomVariableGenerator var = new RandomVariableGenerator();
//rand1 = Computation;
mouldTemp = 55;
System.out.println("Rand 0 is "+ rand1[0]);
System.out.println("Rand 1 is "+ rand1[1]);
System.out.println("Rand 2 is "+ rand1[2]);
double CT = ((0.5/rand[2])*((mouldTemp - rand1[0])/(rand1[1] - mouldTemp)));
double CTA = Math.abs(CT);
return CTA;
}
}
The Random variable generator class is as shown below:
public class RandomVariableGenerator {
public static int[] getRand (){
int rand[] = new int [3];
Random r = new Random ();
int myRandomNumber = 0;
//for (int i=0; i < 1 ; i++)
myRandomNumber = r.nextInt(15) + 5;
System.out.println("Chilled water temperature:" + myRandomNumber);
rand[0] = myRandomNumber;
Random rn = new Random ();
int myNumber = 0;
// (for int i=0; i < 1; i++)
myNumber = rn.nextInt(25) + 50;
System.out.println("Heated water temperature:" + myNumber);
rand[1]= myNumber;
Random rm = new Random ();
int myRandNumber = 0;
// (for int i=0; i < 1; i++)
myRandNumber = rm.nextInt(2) + 6;
System.out.println("Tank Volume:" + myRandNumber);
rand[2]= myRandNumber;
return rand;
}
}
Declare an instance int vector to hold the three values at object (instance) level (rndVars[3])
public class Computation {
public int meltTemp;
//public void mTemp;
public int mouldTemp;
public int setTemp;
public int Q;
public int volume;
public double Cp;
public int actualMouldTemp;
public double dT;
public int AMT ;//= Math.abs(dT);
public double mTemp;
private int [] rndVars = new int[3];
...
Have a public method setRandomVars() you can call whenever you need the 3 values to be reset.
public void setRandomVars(){
rndVars[0] = RandomVariableGenerator.getRand();
rndVars[1] = RandomVariableGenerator.getRand();
rndVars[2] = RandomVariableGenerator.getRand();
}
You could make all of the 3 random variables private and to the class, not the function. Then, when you need a new set call a function that resets them.
For example:
public class MyClass{
//replace these with the actual types/variables you need
int var1;
double var2;
double var3;
/**
*Call this function when you need a new set of variables
**/
public void resetVariables(){
//Change this to the random class you would prefer to use
Random random = new Random(System.currentTimeMillis());
var1 = random.nextInt();
var2 = random.nextDouble();
var3 = random.nextDouble();
}
//put your other functions here except remove the declarations for var1, var2, and var3
/*
ex.
public int myFunction(){
Random random = new Random(System.currentTimeMillis());
int var1 = random.nextInt();
return var1 * 2;
}
becomes
public int myFunction(){
// use the global variable instead of the function's variable
return var1 * 2;
}
*/
}
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.