1

I've got a function that gets called every few milliseconds that needs to convert a double to a character array, string, or other method of storing text. It's immediately written to the screen using Androids "canvas.drawText" function after being converted. At the moment, I'm using String.valueOf(doubletype), but that allocates a new String object every time the loop runs.

I'm wondering if there is another way I can convert this double into a string or char array, etc, without allocating and collecting memory each time the loop runs. Am I missing something obvious?

VerTiGo_Etrex
  • 139
  • 11
  • No, not really. `valueOf(double)` always creates a new String (as would `"" + double`). Is this actually a problem with the performance? `String.format` *might* be beneficial if there were *other* string operations that also had to be done .. – user2246674 May 15 '13 at 22:09
  • Have you tried simply `"" + doubletype` – Craig May 15 '13 at 22:10
  • Follow the answers of these questions. it's already asked http://stackoverflow.com/questions/10553710/fast-double-to-string-conversion-with-given-precision http://stackoverflow.com/questions/15176800/java-most-efficient-way-to-convert-string-to-double – Laksitha Ranasingha May 15 '13 at 22:11
  • the `gc` usually does a pretty good job, are you sure you need to do this? – 0x6C38 May 15 '13 at 22:11
  • @user2246674, it's allocating (and freeing) 2 megabytes of memory every second per function, and I have a few functions that do this, so yes. – VerTiGo_Etrex May 15 '13 at 22:12
  • @VerTiGo_Etrex Does this need to occur? If it does then .. it needs to occur. If there are multiple updates for the same value in a row, a simple "cache variable" could be used (e.g. either don't redraw or keep the last string and redraw that) .. might help, or might not. This could include *limiting* the updates to force the same value to be used in successive updates. I would dare say a human won't notice the value changing above about 30fps. – user2246674 May 15 '13 at 22:13
  • Why can't I just put this into a char array or something though? Then I don't have to allocate a new string every time, I can just reuse the array. – VerTiGo_Etrex May 15 '13 at 22:14
  • If you really need to you can force garbage collection using `System.gc()` – 0x6C38 May 15 '13 at 22:15
  • For instance, I made a function that does this for strings [link](http://pastebin.com/aKtDacXk). – VerTiGo_Etrex May 15 '13 at 22:25
  • What about a StringBuilder? – arynaq May 15 '13 at 22:36
  • Like user2246674 said, a stringbuilder will allocate a new string. If it reused the same memory, it would be fine, but it doesn't. – VerTiGo_Etrex May 15 '13 at 22:38
  • Do you really need to update the display every few milliseconds? 24 times a second is what they use in movies. – user207421 May 15 '13 at 23:38
  • @VerTiGo_Etrex how did you solve this? – 0x6C38 Jul 15 '13 at 15:33
  • @MrD I posted some code I found in a Google sample project that serves my needs. – VerTiGo_Etrex Jul 16 '13 at 16:32

1 Answers1

1

While searching for efficient gesture detection code, I stumbled upon a function that converts decimal numbers to char arrays in an example program written by Google. It serves my needs perfectly.

The original code can be found here: http://developer.android.com/training/gestures/index.html (Click "try it out" on the right to download the zip containing the project)

I've copied the relevant function here, just in case.

private static final int POW10[] = {1, 10, 100, 1000, 10000, 100000, 1000000};

/**
     * Formats a float value to the given number of decimals. Returns the length of the string.
     * The string begins at out.length - [return value].
     */
    private static int formatFloat(final char[] out, float val, int digits) {
        boolean negative = false;
        if (val == 0) {
            out[out.length - 1] = '0';
            return 1;
        }
        if (val < 0) {
            negative = true;
            val = -val;
        }
        if (digits > POW10.length) {
            digits = POW10.length - 1;
        }
        val *= POW10[digits];
        long lval = Math.round(val);
        int index = out.length - 1;
        int charCount = 0;
        while (lval != 0 || charCount < (digits + 1)) {
            int digit = (int) (lval % 10);
            lval = lval / 10;
            out[index--] = (char) (digit + '0');
            charCount++;
            if (charCount == digits) {
                out[index--] = '.';
                charCount++;
            }
        }
        if (negative) {
            out[index--] = '-';
            charCount++;
        }
        return charCount;
    }
VerTiGo_Etrex
  • 139
  • 11