Home > Software engineering >  How to structure a Vector Class that works with real and complex numbers in Java?
How to structure a Vector Class that works with real and complex numbers in Java?

Time:12-30

I have been attempting to make a linear algebra library in Java. I had a Vector class and Complex Number class already created, where the Vector class already had methods and operations which worked with real numbers (typical doubles and ints). The Vector class previously had an attribute data[] which contained the values for the numbers in the vector. However I now added other attributes cData[] and isComplex - which if the Vector is initialized with a different constructor, isComplex is set to true and cData contains the Complex values for the Vector. My goal is to make the class as seamless to the user as possible so that they can create a Vector with either real or complex values with the same class.

However, I was running into some errors due to the nature of Java. Specifically my .get() method would have to have two different return types depending on whether isComplex is true or not which is not possible. This is because I was intending to return a real value (double) if the Vector was Real and a complex value (Complex) if the Vector was initialized as complex. Does anyone have any ideas on what I could try or what routes I could take to better structure this class? (attributes/methods/etc)

So far my ideas have been

  • To make two different attributes each one containing either the real and imaginary components of numbers
    • Run into the same issue with .get()
  • Having a data attribute (array of doubles) and cData attribute (array of Complex numbers) and isComplex boolean and handling methods differently depending on what is the case
    • Still run into the same issue with .get()
  • To make the Vector class purely take in Complex Numbers
    • Not sure if this would be the best case for the user

Here is my current approach and a couple of methods:

public class Vector {
   private double[] data;
   private Complex[] cData;
   private boolean isComplex = false;
   public final int length;

   public Vector(double[] vector) {
       this.data = vector;
       this.length = vector.length;
   }

   public Vector(String[] vector) throws ConstructFormatException {
       Complex[] array = new Complex[vector.length];
       for(int i = 0; i < vector.length; i  ){
           array[i] = new Complex(vector[i]);
       }
       this.cData = array;
       this.isComplex = true;
       this.length = vector.length;
   }

   public void add(Vector vector) throws OperationUndefinedException{
       if(this.isComplex){
           //
       } else {
           MatrixOperation function = (d1, d2) -> {return d1   d2;};
           applyOperation(vector, function);
       }
   }

   public double get(int index) throws OperationUndefinedException{
       if(index >= data.length){
           throw new OperationUndefinedException(INDEX_OUT_RANGE);
       }
       return data[index];
   }
}

CodePudding user response:

I would advice you to take a look at the Apache Commons Numbers implementation: GitHub You can easily reuse this library.

Another approach would be to create a base interface e.g. MyNumber which is implemented by a Complex class and a Real class and one of both is used. As return type you can set MyNumber which can handle both.

Or you can use the same approach as Apache, where the real and the imaginary part are both of type double.

Furthermore, in your code you have data and cData. I would advice you to only use data of type complex, because the real numbers are a subset of the complex numbers. Therefore, every real number can be stored as complex number with an imaginary part of 0.0.

CodePudding user response:

By the code snippet you have provided I guess you want to have the ability to mix real value vectors and complex value vectors on the go. Achieving this with a single class may be a bit problematic, so the solution I would propose is next. Create one generic interface Vector<T>, create functions for both, Vector<Double> and Vector<Complex>. After that create two classes which implement their respective functions. for example: class ComplexVector implements Vector<Complex> and class RealVector implements Vector<Double>. Throw unsupported operation wherever applicable (like some java.util.List implementers do).

This approach will give u flexibility to define functions in vector interface either using Generic 'T' or using specific double/Complex types wherever you find fit

Edit: you can have a bool isComplex() function in the interface and both children will implement accordingly, which will give you freedom in your implementations. However you should make sure users won't try to have their own implementations of your Vector interface, or your structure may loose its "seamlessness". Other than that, users will be able to interact with your two child classes directly and interchange between them without problem

  • Related