I have just started learning Java as part of my university course and am having a problem with y first project. I am just starting to create a project that basically sorts coins. I am trying to make a method called printCoinList() that prints the contents of a coin list, indicating what denominations are currently in circulation (i.e "The current coin denominations are in circulation: 200,100,50,20,10), in pennies.
So far I have declared my instance fields, created a parameter and attempted to make this method. My only issue is when i try and test it in the main() method it seems to have a problem with me using an array as the coinList parameter. This is what I have so far:
public class CoinSorter {
//Instance Fields
String currency;
int minCoinIn;
int maxCoinIn;
int[] coinList;
//constructor
public CoinSorter(String Currency, int minValueToExchange, int maxValueToExchange, int[] initialCoinList) {
currency=Currency;
minCoinIn=minValueToExchange;
maxCoinIn = maxValueToExchange;
coinList= initialCoinList;
}
public void printCoinList() {
System.out.println("The current coin denominations are in circulation"
+ coinList);
}
public static void main(String[] args) {
//An example
CoinSorter exampleOne = new CoinSorter("pounds", 0, 10000, {10,20,50,100,200});
The only problems seems to be in exampleOne as when I take this out the rest of the code seems to run fine.
The error message is:
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
The constructor CoinSorter(String, int, int, int, int, int, int, int) is undefined
Syntax error on token "{", delete this token
Syntax error on token "}", delete this token
So does anyone know what I am doing wrong?
This is because an array initializer may only be specified at declaration site or as part of an array creation expression. (JLS ยง 10.6)
Below is an array initializer at declaration site.
int[] array = { 2, 3, 5, 7, 11 };
This is short for
int[] array = new int[] { 2, 3, 5, 7, 11 };
However, it may not be used as 'array literal', unlike a string literal. That means that you must write out the array creation expression:
new CoinSorter("pounds", 0, 10000, new int[] { 10, 20, 50, 100, 200 });
Arrays in java can be declared/initialized using one of the following ways.
int[] myIntArray = {10,20,50,100,200};
int[] myIntArray = new int[]{10,20,50,100,200};
replace CoinSorter exampleOne = new CoinSorter("pounds", 0, 10000, {10,20,50,100,200});
with
CoinSorter exampleOne = new CoinSorter("pounds", 0, 10000, myIntArray );
OR
CoinSorter exampleOne = new CoinSorter("pounds", 0, 10000, new int[]{10,20,50,100,200});
Firt of all , in java , you need to specify the type of your Array :
CoinSorter exampleOne = new CoinSorter("pounds", 0, 10000, new int[]{10,20,50,100,200});
Then your "printCoinList" method will not work as excepted , this should print :
The current coin denominations are in circulation [I#7852e922
Your final code should be :
import java.util.Arrays;
public class CoinSorter {
//Instance Fields
String currency;
int minCoinIn;
int maxCoinIn;
int[] coinList;
//constructor
public CoinSorter(String Currency, int minValueToExchange, int maxValueToExchange, int[] initialCoinList) {
currency=Currency;
minCoinIn=minValueToExchange;
maxCoinIn = maxValueToExchange;
coinList= initialCoinList;
}
public void printCoinList() {
System.out.println("The current coin denominations are in circulation : "
+ Arrays.toString(coinList));
}
public static void main(String[] args) {
//An example
CoinSorter exampleOne = new CoinSorter("pounds", 0, 10000, new int[]{10,20,50,100,200});
exampleOne.printCoinList();
}
}
Result :
The current coin denominations are in circulation : [10, 20, 50, 100, 200]
Good luck :) I hope I could access to you future exchange and buy and hold some crypto :D
before creating an object CoinSorter exampleOne = new CoinSorter("pounds", 0, 10000, {10,20,50,100,200}); declare and initialize an array int arr[]={10,20,50,100,200}and then pass it in the constructor rather than passing {10,20,50,100,200}
like this
int arr[]={10,20,50,100,200};
CoinSorter exampleOne = new CoinSorter("pounds", 0, 10000, arr);
Related
I'm trying to find the inverse of a matrix using the Apache Commons Math Library.
Below is my attempt at doing just that:
BigReal[][] leftMatrixData = new BigReal[][] {
{ new BigReal(1), new BigReal(0), new BigReal(0), new BigReal(0) },
{ new BigReal(1), new BigReal(0), new BigReal(1), new BigReal(0) },
{ new BigReal(1), new BigReal(1), new BigReal(0), new BigReal(0) },
{ new BigReal(1), new BigReal(1), new BigReal(1), new BigReal(1) },
};
FieldMatrix<BigReal> leftMatrix = MatrixUtils.createFieldMatrix(leftMatrixData);
FieldMatrix<BigReal> leftMatrixInverse = new FieldLUDecomposition<>(leftMatrix)
.getSolver()
.getInverse();
When I run this, I get the following error:
org.apache.commons.math3.exception.MathArithmeticException: zero not allowed here
at org.apache.commons.math3.util.BigReal.divide(BigReal.java:255)
at org.apache.commons.math3.util.BigReal.divide(BigReal.java:39)
at org.apache.commons.math3.linear.FieldLUDecomposition.<init>(FieldLUDecomposition.java:160)
When I go to line 160 of FieldLUDecomposition.java per the above error message, I see that the library thinks this matrix is Singular i.e. it thinks it has no inverse:
public T getDeterminant() {
if (this.singular) { <---- this is line 160
return (FieldElement)this.field.getZero();
} else {
int m = this.pivot.length;
T determinant = this.even ? (FieldElement)this.field.getOne() : (FieldElement)((FieldElement)this.field.getZero()).subtract(this.field.getOne());
However, doing a quick check on WolframAlpha shows that this matrix has a non-zero determinant and indeed has an inverse:
So the question is - what am I doing wrong and how do I find the inverse of my matrix? Am I using the wrong solver?
Below is based on apache common math 3.6.1
A ticket is raised concerning this issue, I submitted a patch to fix the problem and the fix version will be 4.0 (not yet released as of 2021-07-19)
The reason of issue is equals method in BigReal
#Override
public boolean equals(Object other) {
if (this == other){
return true;
}
if (other instanceof BigReal){
return d.equals(((BigReal) other).d);
}
return false;
}
where d is BigDecimal, the backing value of BigReal. This cause equals comparison return undesired result when two BigReal has d with same value but different scale, and cause error when initializing FieldLUDecomposition. For BigDecimal we should check
return d.compareTo((BigReal) other) == 0;
instead.
Solution:
Check if workaround section(Copy BigReal as local class and change equals) helps.
Wait for version 4.0 release.
If double value matrix is acceptable,
Use RealMatrix instead, and MatrixUtils provide handy inverse method
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealMatrix;
public class CalculateInverse {
public static void main(String[] args) {
double[][] matrixData = new double[][]{
{1, 0, 0, 0},
{1, 0, 1, 0},
{1, 1, 0, 0},
{1, 1, 1, 1}
};
RealMatrix matrix = MatrixUtils.createRealMatrix(matrixData);
RealMatrix inverse = MatrixUtils.inverse(matrix);
System.out.println(inverse);
}
}
I am trying to pass in an array for testing a certain algorithm, but the arrays seem to not be passed correctly or at all. I manually tested the algorithm so I know it works as it's supposed to. How can I pass arrays in for testing in JUnit 5?
#ParameterizedTest
#CsvSource(value = {"[13,14,65,456,31,83],[1331,65456]"})
public void palindromeCombos(int[] input, int[] expected){
Palindrome pal = new Palindrome();
List<Integer> actual = pal.allPalindromes(input);
int[] result = new int[actual.size()];
for(int i = 0; i < actual.size(); i++){
result[i] = actual.get(i);
}
Assertions.assertArrayEquals(expected, result);
}
Pablo's Answer is correct, of course, but personally I'm not a fan of parsing strings if I don't absolutely have to. Another approach could be to use a MethodSource instead, and explicitly provide the arguments you need:
public static Stream<Arguments> palindromeCombos() {
return Stream.of(
Arguments.of(new int[]{13, 14, 65, 456, 31, 83}, new int[]{1331, 65456}));
}
#ParameterizedTest
#MethodSource
public void palindromeCombos(int[] input, int[] expected) {
// Test logic...
}
Since there is not implicit conversion for arrays, you can use explicit conversion, first you need to declare you converter class:
class IntArrayConverter implements ArgumentConverter {
#Override
public Object convert(Object source, ParameterContext context)
throws ArgumentConversionException {
if (!(source instanceof String)) {
throw new IllegalArgumentException(
"The argument should be a string: " + source);
}
try {
return Arrays.stream(((String) source).split(",")).mapToInt(Integer::parseInt).toArray();
} catch (Exception e) {
e.printStackTrace();
throw new IllegalArgumentException("Failed to convert", e);
}
}
}
Then you can use it in your test:
#ParameterizedTest
#CsvSource(value = {
"13,14,65,456,31,83;1331,65456",
"1,2,3,4,5,6;10,20"}, delimiterString = ";")
public void palindromeCombos(#ConvertWith(IntArrayConverter.class) int[] input,
#ConvertWith(IntArrayConverter.class) int[] expected) {
System.out.println(Arrays.toString(input));
System.out.println(Arrays.toString(expected));
}
Notice that I removed the [] from the CsvSource and changed the delimiter to ;, so the arrays are expressed by a list of integers separated by comma.
If you want you can keep the format you had and handle it in the converter class.
For those two examples the output is:
[13, 14, 65, 456, 31, 83]
[1331, 65456]
[1, 2, 3, 4, 5, 6]
[10, 20]
If you need further information you can check this post: https://www.baeldung.com/parameterized-tests-junit-5
Just for reference, I've taken like one high school class on Java, so this question should be super easy to respond to. I'm just having trouble figuring out a way to call a class method, the constructor, as a new object without putting in new values for the parameters. The constructor looks like this:
public Skills(int courage, int intelligence, int stamina, int crafting,
int blacksmithery, int herbalism, int slingSkill,
int bowSkill, int swordSkill, int armor, int stealth, int
lifeForceSkill){
this.courage = courage;
this.intelligence = intelligence;
this.stamina = stamina;
this.crafting = crafting;
this.blacksmithery = blacksmithery;
this.herbalism = herbalism;
this.slingSkill = slingSkill;
this.bowSkill = bowSkill;
this.swordSkill = swordSkill;
this.armor = armor;
this.stealth = stealth;
this.lifeForceSkill = lifeForceSkill;
}
And when I establish it it my main method I do this:
Skills skills = new Skills(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
To set all the levels to 1 and then I have the object skills to work with later. (Am I getting the terms constructors and objects mixed up? If it's wrong just switch them all in your mind I think I'm being consistent with it at least).
The problem is I have a toString() method in the Skills class that I want to call in a separate method in the main class.
else if (optionChoice.equalsIgnoreCase("View Skills")){
Skills skills = new Skills();
System.out.println(skills.toString());
break;
}
Of course the object I create here throws an error because I cannot just write Skills(); without putting in all twelve values for the parameter. So how do I call the method from the Skills class when I can't create an object for it? It's imperative to functionality that the values do not change, and since they are variable and change with the program, I can't put any value in for them.
I know it's probably a super basic question but that's the level I'm at so any super basic answers would be helpful. Shouldn't take too much of your time. Thanks in advance!
Why not just make your skills object a static field instead of creating it within the main method?
public class WhateverYourClassIsCalled {
static Skills skills = new Skills(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
public static void main(String[] args) {
// ...
}
void yourOtherMethod() {
// ...
else if (optionChoice.equalsIgnoreCase("View Skills")) {
System.out.println(skills.toString());
break;
}
}
}
*I made an array.. at the class level,but assigned it's values inside a method.. but for some reason.. it gave up an error..
then when i did the array declaration & assignment inside of the same method..
everything functioned smoothly!! Why is that? I declared the array at class level.. so it has class scope right?? so why can't i assign it values inside a method?? I'm utterly confused :/ *
public class VacationScale{
public int [] days;
days = new int [7];
public void setVacationScale(){
days[0]=10;
days[1]=15;
days[2]=15;
days[3]=15;
days[4]=20;
days[5]=20;
days[6]=25;
}
public void displayVacationDays(int yearsOfService){
if(yearsOfService >=0 && yearsOfService<=6){
System.out.println("the years of the service of the employee is "
+yearsOfService+ " and hence the employee is eligible to :"
+days[yearsOfService]+ " holidays");
}
else if(yearsOfService >6){
System.out.println("the years of the service of the employee is "
+yearsOfService+ " and hence the employee is eligible to :25"
+" holidays");
}
else{
System.out.println("invalid number of years of service");
}
}
}
The error that shows up on the command prompt is-- identifier expected
The line days = new int [7]; is invalid code outside of a method. Instead write:
public int [] days = new int [7];
which will both declare and initialize the array.
Beyond this, there is no need for your setVacationScale() method, since it appears to be hardcoded. Instead, you can initialize the array to have these values:
public int [] days = new int[] {10, 15, 15, 15, 20, 20, 25};
To give a few more tips, it's unwise to expose access to the array outside the class if it's only used by the class's methods - if this is the case change its access modifier to private. And as long as the array is only initialized once, it's good form to make it final:
private final int [] days = new int[] {10, 15, 15, 15, 20, 20, 25};
This statement is not valid to put in the class declaration:
days = new int[7];
Change it to an inline initialization:
public int[] days = new int[7];
Or put it in an initialization block:
{
days = new int[7];
}
Or move it into the constructor.
public class VacationScale{
public int [] days;
days = new int [7];
That snippet appears to be causing your problem. You cannot assign a new value to days outside a method.
Perhaps you could try assigning it at the start of setVacationScale():
public void setVacationScale() {
days = new int [7];
days[0]=10;
// ...
I am creating a method where if you pass in a parameter of type Random, then it will return a random object. Here is basically what I am trying to do:
public T choose(Random r) {
int randomInt = r.nextInt(randomList.size()); // randomList is just a instance variable
return randomList.get(randomInt);
}
The random list has this the following strings:[2, 2, 2, 1, 1, 1, 1, c, c, c, a, a, a, a]
Then I made a driver with the following code
for (int i = 0; i < 10; i++) {
System.out.print(rndList.choose(rnd)); // rnd is initialized as a static Random variable
}
However my outputs are not coming out random. I used the debugger and found out that my choose method generates an integer that is relatively low, so it will always print out either 2's or 1's but never c's or a's. I can't figure out why this is happening and help would be greatly appreciated.
EDIT: Problem was solved. I left out alot of detail, but when I called the size() method, that was something I overwrote which had an error which would return a smaller number than I would have liked. Thanks to dtech for noticing my silly mistake. Thank you for everyone who tried to help me!
At first glance nothing seems wrong with the code, so it might just be a random result. But your "Print it and check" method is very unreliable. Just use something like this:
final int N = 10000; // test 10.000 times
HashTable<Object, Integer> count = new HashTable(N);
for(int i=0;i < N;i++){
Object o = rndList.choose(rnd);
count.put(o, (count.get(o)==null?0:count.get(o))+1);
}
for(Map.Entry<Object, Integer> map : count.entrySet()){
System.out.println(String.format("%s: %d", map.getKey().toString(), map.getValue()));
}
This will print on average something like:
2: 1429
1: 2857
c: 2143
a: 2857
Only if the numbers differ creatly you should be concerned.
Also make sure that you use the new Random() constructor, not new Random(somenumber). If you use the latter you will get the same number sequence every time.
send you random initialization code, are you getting exactly the same results each time? are you using a seed to create the Random object?
Here is the code I used. You need to provide more code to see why yours doesn't work.
public class Main<T> {
private List<T> randomList = new ArrayList<T>();
public T choose(Random r) {
int randomInt = r.nextInt(randomList.size()); // randomList is just a instance variable
return randomList.get(randomInt);
}
public static void main(String... args) throws IOException, InterruptedException, ExecutionException {
Main<String> rndList = new Main<String>();
rndList.randomList.addAll(Arrays.asList("2, 2, 2, 1, 1, 1, 1, c, c, c, a, a, a, a".split(", ")));
Random rnd = new Random();
for (int i = 0; i < 10; i++) {
System.out.print(rndList.choose(rnd)); // rnd is initialized as a static Random variable
}
}
}
prints
1ca1caa1a2