0

I have written the following program which takes the duplicates in the doubleArray and adds them to a counter.

Then I wrote a for loop to print out the values in the array going from the smallest value, up by 0.1, to the highest value. Then the program is supposed to put a dollar sign after each number that is represented in the array.

double[] doubleArray = {1.7,1.7,2.0,1.3,1.0};
int count = 0;          
Arrays.sort(doubleArray);  
for(int i = 0;i<doubleArray.length-1;i++){
    for(int j =i+1;j<doubleArray.length;j++){
        if (doubleArray[i] == doubleArray[j]) {
            count++;
        } else {
            break;
        }
    }
}

int finalDub = doubleArray.length;
double min = doubleArray[0];
double max = doubleArray[finalDub - 1];

for (double i = min; i < max+0.1; i += 0.1) {
    System.out.printf("%.1f ", i);  
    System.out.print("$".repeat(count));
    System.out.print("\n");
}

But when I run the code, the following gets outputted

1.0 $
1.1 $
1.2 $
1.3 $
1.4 $
1.5 $
1.6 $
1.7 $
1.8 $
1.9 $
2.0 $

When it should be the following because I want it to add the $ only after a double represented in the array, and multiple '$''s for duplicate values.

1.0 $
1.1 
1.2 
1.3 $
1.4 
1.5 
1.6 
1.7 $$
1.8 
1.9 
2.0 $

I believe what is happening is the count integer is being set once and never updating. Either way, how can I update my counter logic to represent what I want to be outputted?

Adrian Shum
  • 38,812
  • 10
  • 83
  • 131
  • 3
    You could create a `Map` that maps each value with it's count in the array. – 001 May 02 '22 at 23:57
  • Isn't that for changing doubles into integers? How would I be able to use this to represent the count in the third for loop for the current i value? –  May 03 '22 at 00:12
  • Meh. I just tested it out and there is a problem with floating point rounding errors. Maybe not a good solution after all. – 001 May 03 '22 at 00:24
  • The line **System.out.print("$".repeat(count));** never switches variables/indexes/values/etc. It is only printing the one integer value for **count**. – Kemper Lee May 03 '22 at 00:31
  • @KemperLee I know, how could I change it so it is updated for each value –  May 03 '22 at 00:32
  • you keep on updating the same `count` variable. Instead you should have separate count for each value. And, learn to properly format your code. – Adrian Shum May 03 '22 at 00:36
  • 1
    I think this use case may be suspect. Double precision floating point variables contain *approximate*, not exact, values. In particular, there is no way for Java to accurately represent the value 0.1 (or any integer multiple of it) exactly. Any computation that is supposed to result in such a value may not match a key that is supposed to be a multiple of 0,1. I question the logic of using `double` values as map keys in this case. – scottb May 03 '22 at 02:28

3 Answers3

2

I made a custom Counter class to keep track of each Double and the counts of the Double. You can iterate through all your doubles, add the non-duplicates, and if duplicate, increment count.

import java.util.ArrayList;
import java.util.Arrays;

public class test {

    static class Counter{
        Double value;
        int count;

        Counter(Double d, int c){
            this.value = d;
            this.count = c;
        }

        public String toString() { return value+":"+count; }
    }

    public static void main(String[] args){
        double[] doubleArray = {1.7,1.7,2.0,1.3,1.0};
        ArrayList<Counter> list = new ArrayList<>();

        Arrays.sort(doubleArray);
        for(int i = 0;i<doubleArray.length;i++){
            int size = list.size();
            if (size == 0){
                list.add(new Counter(doubleArray[0], 1));
            }else{
                Counter current = list.get(size-1);
                if (doubleArray[i] != current.value){
                    list.add(new Counter(doubleArray[i], 1));
                }else{
                    current.count = current.count +1;
                }
            }
        }

//        for (int i=0; i< list.size(); i++){
//            System.out.println(list.get(i).toString());
//        }

        int finalDub = doubleArray.length;
        double min = doubleArray[0];
        double max = doubleArray[finalDub - 1];

        for (double i = min; i < max+0.1; i += 0.1) {
            int count = 0;
            System.out.printf("%.1f ", i);
            for (int j=0; j< list.size(); j++){
                Counter obj = list.get(j);
                double val = Double.parseDouble(String.format("%.1f", i));  
//this is necessary to format the floating point number to the exact accuracy stored in your array
                if (obj.value == val){
                    count = obj.count;
                    break;
                }else{
                    continue;
                }
            }
            System.out.print("$".repeat(count));
            System.out.print("\n");
        }
    }
}

I also found that for some reason, your loop to iterate through values from min to max have some floating point issues that cause it to not have the same value as the double stored in the array. floating point error looks fine now

  • The floating point issue was addressed in this SO link https://stackoverflow.com/a/322875/16034206 – experiment unit 1998X May 03 '22 at 02:20
  • 1
    I assume that given how to address the floating point issue, you can use the Map that was mentioned by @Johnny_Mopp. it would probably be more efficient, since my implementation of a custom class is just a poor imitation of Map anyway. – experiment unit 1998X May 03 '22 at 02:25
0

BUG FOUND o_o (REFERENCE ONLY)

NOTE THIS IS NOT A FULL SOLUTION ONLY A RECOMMENDATION

Instead of creating a nested loop with a break statement, I would 1000% recommend an approach closer to this.

    int size = doubleArray.length - 1, count = 0;
    double number = doubleArray[0];

    for(int index = 1; index < size; index++)
    {
        if(number == doubleArray[index])
        {
            count++;
        }
        number = doubleArray[index + 1];
    }

Though I do not know exactly where the issue is with your code, the easier it is to read the easier the bug will be to find!

EDIT after MY found bug ha

This part works great and is what you want

if(number == doubleArray[index])
{            
    count++;
}

But if this is in the for-loop,

number = doubleArray[index + 1];

Each number after that will be considered a match.

Kemper Lee
  • 276
  • 4
  • 10
0

How could I change it so it is updated for each value

If you create a second array to track each digit you could do so pretty reliably, though I am sure there are more efficient ways out there.

int[] digitCount = new int[11]; // 1.0 - 2.0
...
if(number == doubleArray[index])
{
    digitCount[number]++;
}
...

And then down in your print

...
System.out.print("$".repeat(digitCount[i]));
...

Make sure that the i (or whatever you call it) is a WHOLE number because you cannot have decimal indecies.

Kemper Lee
  • 276
  • 4
  • 10