1

I had to write a program that will receive an int 'n' and another one 'd' - and will print the number n with commas every d digits from right to left. If 'n' or 'd' are negative - the program will print 'n' as is. I although had to make sure that there is no commas before or after the number and I'm not allowed to use String or Arrays.

for example: n = 12345678

d=1: 1,2,3,4,5,6,7,8

d=3: 12,345,678

I've written the following code:

public static void printWithComma(int n, int d) {
    if (n < 0 || d <= 0) {
        System.out.println(n);
    } else {
        int reversedN = reverseNum(n), copyOfrereversedN = reversedN, counter = numberLength(n);
        while (reversedN > 0) {
            System.out.print(reversedN % 10);
            reversedN /= 10;
            counter--;
            if (counter % d == 0 && reversedN != 0) {
                System.out.print(",");
            }
        }
        /*
         * In a case which the received number will end with zeros, the reverse method
         * will return the number without them. In that case the length of the reversed
         * number and the length of the original number will be different - so this
         * while loop will end the zero'z at the right place with the commas at the
         * right place
         */
        while (numberLength(copyOfrereversedN) != numberLength(n)) {
            if (counter % d == 0) {
                System.out.print(",");
            }
            System.out.print(0);
            counter--;
            copyOfrereversedN *= 10;
        }
    }
}

that uses a reversNum function:

// The method receives a number n and return his reversed number(if the number
// ends with zero's - the method will return the number without them)
public static int reverseNum(int n) {
    if (n < 9) {
        return n;
    }
    int reversedNum = 0;
    while (n > 0) {
        reversedNum += (n % 10);
        reversedNum *= 10;
        n /= 10;
    }
    return (reversedNum / 10);
}

and numberLength method:

// The method receives a number and return his length ( 0 is considered as "0"
// length)
public static int numberLength(int n) {
    int counter = 0;
    while (n > 0) {
        n /= 10;
        counter++;
    }
    return counter;
}

I've been told that the code doesn't work for every case, and i am unable to think about such case (the person who told me that won't tell me).

Thank you for reading!

RedYoel
  • 302
  • 2
  • 16

4 Answers4

1

Your code seems overly complicated.

If you've learned about recursion, you can do it like this:

public static void printWithComma(int n, int d) {
    printInternal(n, d, 1);
    System.out.println();
}
private static void printInternal(int n, int d, int i) {
    if (n > 9) {
        printInternal(n / 10, d, i + 1);
        if (i % d == 0)
            System.out.print(',');
    }
    System.out.print(n % 10);
}

Without recursion:

public static void printWithComma(int n, int d) {
    int rev = 0, i = d - 1;
    for (int num = n; num > 0 ; num /= 10, i++)
        rev = rev * 10 + num % 10;
    for (; i > d; rev /= 10, i--) {
        System.out.print(rev % 10);
        if (i % d == 0)
            System.out.print(',');
    }
    System.out.println(rev);
}
Andreas
  • 154,647
  • 11
  • 152
  • 247
  • 1
    That code is complicated for sure,but i'm not allowed to use neither Strings, Arrays or recursion. – RedYoel Dec 29 '19 at 19:29
1

You solved looping through the digits by reversing the number, so a simple division by ten can be done to receive all digits in order.

The comma position is calculated from the right.

public static void printWithComma(int n, int d) {
    if (n < 0) {
        System.out.print('-');
        n = -n;
    }
    if (n == 0) {
        System.out.print('0');
        return;
    }
    int length = numberLength(n);
    int reversed = reverseNum(n);

    for (int i = 0; i < length; ++i) {
        int nextDigit = reversed % 10;
        System.out.print(nextDigit);
        reversed /= 10;

        int fromRight = length - 1 - i;
        if (fromRight != 0 && fromRight % d == 0) {
            System.out.print(',');
        }
    }
}

This is basically the same code as yours. However I store the results of the help functions into variables.

A zero is a special case, an exception of the rule that leading zeros are dropped.

Every dth digit (from right) needs to print comma, but not entirely at the right. And not in front. Realized by printing the digit first and then possibly the comma.

The problems I see with your code are the two while loops, twice printing the comma, maybe? And the println with a newline when <= 0.

Test your code, for instance as:

public static void main(String[] args) {
    for (int n : new int[] {0, 1, 8, 9, 10, 234,
                   1_234, 12_345, 123_456, 123_456_789, 1_234_567_890}) {
        System.out.printf("%d : ", n);
        printWithComma(n, 3);
        System.out.println();
    }
}
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • 1
    Since `reverseNum()` from the question is flawed, and you're using it, your code is flawed. `printWithComma(999999999, 3)` prints `935,600,141` – Andreas Dec 30 '19 at 07:02
  • @Andreas this is a homework task or such, I did refrain rewriting it for the OP, despite seeing that hacky code. – Joop Eggen Dec 31 '19 at 00:59
  • The OP mentioned that already someone told him about there being a flaw. Simplifying printWithComma should help. – Joop Eggen Dec 31 '19 at 01:09
  • Simplifying? You mean like [this](https://stackoverflow.com/a/59522597/5221149)? ;-) – Andreas Dec 31 '19 at 04:32
  • @Andreas yes that is the best solution, though I did want to follow the OP's work a bit.. – Joop Eggen Dec 31 '19 at 13:25
0

Are you allowed to use the whole Java API?

What about something as simple as using DecimalFormat

double in = 12345678;
DecimalFormat df = new DecimalFormat( ",##" );
System.out.println(df.format(in));

12,34,56,78


Using...

  • ,# = 1 per group
  • ,## = 2 per group
  • ,### = 3 per group etc...
Matt Clark
  • 27,671
  • 19
  • 68
  • 123
  • I guess, it isn't. – Nikolas Charalambidis Dec 29 '19 at 20:16
  • Question says *"I'm not allowed to use String or Arrays"*. `",##"` is a string (literal), and the return value of `format()` is a string too. Beside, the input is *"an int 'n' and another one 'd'"*, so how would you get this code from that input, *at runtime*? – Andreas Dec 30 '19 at 06:50
0

It took me a bunch of minutes. The following code snippet does the job well (explanation below):

public static void printWithComma(int n, int d) {             // n=number, d=commaIndex

    final int length = (int) (Math.log10(n) + 1);                   // number of digits;

    for (int i = 1; i < Math.pow(10, length); i*=10) {        // loop by digits
        double current = Math.log10(i);                       // current loop
        double remains = length - current - 1;                // loops remaining
        int digit = (int) ((n / Math.pow(10, remains)) % 10); // nth digit

        System.out.print(digit);                              // print it

        if (remains % d == 0 && remains > 0) {                // add comma if qualified
            System.out.print(",");
        }
    }
}
  • Using (Math.log10(n) + 1) I find a number of digits in the integer (8 for 12345678).
  • The for-loop assures the exponents of n series (1, 10, 100, 1000...) needed for further calculations. Using logarithm of base 10 I get the current index of the loop.
  • To get nth digit is a bit tricky and this formula is based on this answer. Then it is printed out.
  • Finally, it remains to find a qualified position for the comma (,). If modulo of the current loop index is equal zero, the dth index is reached and the comma can be printed out. Finally the condition remains > 0 assures there will be no comma left at the end of the printed result.

Output:

For 4: 1234,5678

For 3: 12,345,678

For 2: 12,34,56,78

For 1: 1,2,3,4,5,6,7,8

Community
  • 1
  • 1
Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183