Convert an integer to a string without allocating memory - java

I've been experiencing occasional lags in my Android game when the garbage collector runs. I ran DDMS and discovered that all of the memory being allocated by my application is from this line:
scoreString = String.valueOf(score);
What is the best way to convert an integer to a string without allocating any memory?

Allocate an array of characters to be displayed as the score, and use a lookup table of 0-9 (this conveniently maps to a 0-base array anyway) to append to this array based on each digit of the score.
Edit:
To extract the digits from your score:
12345 mod 10 = 5
12345 mod 100 = 45 / 10 = 4.5 (floors to 4)
12345 mod 1000 = 345 / 100 = 3.45 (floors to 3)
12345 mod 10000 = 2345 / 1000 = 2.345 (floors to 2)
12345 mod 100000 = 12345 / 10000 = 1.2345 (floors to 1)
Also you'll know what the max length for the score character array should be based on whatever you're using to store score (i.e. int)
I recommend reverse-filling this array and initializing it to all '0' so your score will display like
0000000000
0000005127

I just ran into this problem also, if the GC kicks in during a frame it's really noticeble. I came up with this solution.
If you fill the buffer backwards, you can just repeatedly % 10 and / 10.
A working implementation that appends a number to a StringBuilder, probably not the best way to do it but it works and causes no allocations. You could also use another character array for the values instead of casting to char and adding 48 ('0' in ascii)
private char[] sbBuffer = new char[20];
private void appendInt(StringBuilder sb, int num) {
int i,j;
i = sbBuffer.length - 1;
if (num == 0) {
j = sbBuffer.length - 1;
sbBuffer[j] = (char) 48;
} else {
if (num < 0)
sb.append('-');
num = Math.abs(num);
while (num > 0) {
sbBuffer[i] = (char) (num % 10 + 48);
i--;
num /= 10;
}
j = i + 1;
}
sb.append(sbBuffer, j, sbBuffer.length - j);
/* clean up */
for (i = j; i < sbBuffer.length; i++)
sbBuffer[i] = 0;
}

Related

Java:Three digit Sum - Find out all the numbers between 1 and 999 where the sum of 1st digit and 2nd digit is equal to 3rd digit

Problem statement: Three digit sum - Find all the numbers between 1 and 999 where the sum of the 1st digit and the 2nd digit is equal to the 3rd digit.
Examples:
123 : 1+2 = 3
246 : 2+4 = 6
Java:
public class AssignmentFive {
public static void main(String[] args) {
int i=1;
int valuetwo;
int n=1;
int sum = 0;
int valuethree;
int valueone = 0;
String Numbers = "";
for (i = 1; i <= 999; i++) {
n = i;
while (n > 1) {
valueone = n % 10;/*To get the ones place digit*/
n = n / 10;
valuetwo = n % 10;/*To get the tens place digit*/
n = n / 10;
valuethree = n;/*To get the hundreds place digit*/
sum = valuethree + valuetwo;/*adding the hundreds place and
tens place*/
}
/*Checking if the ones place digit is equal to the sum and then print
the values in a string format*/
if (sum == valueone) {
Numbers = Numbers + n + " ";
System.out.println(Numbers);
}
}
}
}
I got my result :
1
10
100
1000
10000
100000
1000000
10000000
100000000
1000000000
10000000001
100000000011
1000000000111
10000000001111
100000000011111
1000000000111111
10000000001111111
100000000011111111
1000000000111111111
Process finished with exit code 0
The result is not showing the actual result like it should be which should show values like: 123, 246 (Please refer to the problem statement above.)
Please let me know what seems to be the issue with the code and how to tweak it.
Don't know what you're trying to do with that while loop, or why you are building up a space-separated string of numbers.
Your code should be something like:
for (int n = 1; n <= 999; n++) {
int digit1 = // for you to write code here
int digit2 = // for you to write code here
int digit3 = // for you to write code here
if (digit1 + digit2 == digit3) {
// print n here
}
}
So basically your question is how to calculate the numbers, right?
My first hint for you would be how to get the first, second and third value from a 2 or 3 digit number.
For example for 3 digits you can do int hundretDigit = (n - (n % 100)) % 100. Of course this is really inefficient. But just get code working before optimizing it ;)
Just think about a way to get the "ten-digit" (2nd number). Then you add them and if they equal the third one you write System.out.println(<number>);
EDIT:
For 2 digit numbers I will give you the code:
if(i >= 10 && i <= 99) {
int leftDigit = (i - (i % 10)) / 10;
if(leftDigit == (i % 10)) {
//Left digit equals right digit (for example 33 => 3 = 3
System.out.println(i);
}
}
Try again and edit your source code. If you have more questions I will edit my (this) answer to give you a little bit more help if you need!

I can generate random numbers, but not identify min and max correctly in my set of numbers

So below is a script that will generate a list of n amount of random numbers between 1-100. I need to get it to where I can also identify the max and min of the random numbers generated in the command prompt after it runs the script. I keep running into the problem where it will just duplicate the number 2 additional times. Example when n= 2: 12 12 12 43 43 43 22 22 22
I think my problem is that when I use int min = Math.min(b,b); the for loop wants to repeat that part too. But if I put it outside of the script then I no longer have the variable b to use.
int n = Integer.parseInt(args[0]);
for(int i = 0; i < n; i++)
{
int b = (int)(Math.random() * (100 - 1)) + 1;
System.out.println(b);
}
if you insist on using Math library, you should consider the first number as min and max.
int n = Integer.parseInt(args[0]);
int max = 0;
int min = 0;
for(int i = 0; i < n; i++){
int b = (int)(Math.random() * (100 - 1)) + 1;
if(i == 0){
min = b;
max = b;
}else{
min = Math.min(min,b);
max = Math.max(max,b);
}
System.out.println(b);
}
System.out.println(String.format("Min:%d , Max:%d",min,max));
The Random class can generate streams of random numbers (with
lower/upper bound).
IntSteam can be collected into IntSummaryStatistics, which provide min/max/avg/sum/count information on the streamed data.
When streaming, you can output (or process) the items over an identity function.
Combining all these results in a simple and elegant solution:
int n=Integer.parseInt(args[0]);
IntSummaryStatistics statistics = new Random()
.ints(1, 100)
.limit(n)
.map(i -> {
System.out.println(i);
return i;
}).summaryStatistics();
System.out.println("min: " + statistics.getMin());
System.out.println("max: " + statistics.getMax());
first the word script in your question means the programming language ( javascript) ?
or you mean the word script ( probably in java we call it a class or program not a script the word script is mainly used in python )
look easy fast way is to push the elements generated into an array and sort it
Vector x=new Vector();
for(int i=0;i<10;i++)
{
x.add(i,(Math.random() * (100 - 1)) + 1);
//System.out.println(x.elementAt(i));
}
Collections.sort(x);
System.out.println(x.elementAt(0));
System.out.println(x.elementAt(x.size()-1));

Difference between Modulo in Java and VBScript

Is there a difference between the way that the Modulo operates calculates values in Java vs the way that it does in VBScript?
Both of these are returning a digit that I am using as part of a larger number later in the code but I believe the issue is between the way VBScript and Java are handling the Mod operator. I may be wrong though.
I am trying to work through reasons why I am seeing different outputs from when I run the below VBscript code block vs my replicated version in Java, sorry for the delay in updating the post.
The function takes in a String and then works to determine a return digit based upon the logic in the loop. The missing code just has to do with initializing the variables used, and determining the length of the string to loop over.
Any help would be greatly appreciated! Thank you
VBScript:
For i=1 to Length
CurrentNumber = Mid(CCNumber,i,1)
CurrentNumber = Int(CurrentNumber)
If (i mod 2) <> 0 then
ModNumber = CurrentNumber * 2
If ModNumber > 9 then
Total = Total + 1 + (ModNumber mod 10)
Else
Total = Total + ModNumber
End If
Else
Total = Total + CurrentNumber
End If
Next
cd = ((Int(Total/10) + 1) * 10) - Total
if cd = 10 then cd = 0
CheckDigit = cd
Java:
for (i=0; i<length; i++)
{
String currentNumberString = CCNumber.substring(i,i+1);
currentNumber = Integer.valueOf(currentNumberString);
if (i % 2 != 0)
{
Integer ModNumber = currentNumber * 2;
if (ModNumber > 9)
{
total = total + 1 + (ModNumber % 10);
}
else
{
total = total + ModNumber;
}
}
else
{
total = total + currentNumber;
}
}
int cd = ((Integer.valueOf(total/10) + 1) * 10) - total;
if (cd == 10)
{
cd = 0;
}
return cd;
}
One difference: The Mod operator in VBScript always returns an integer. Java's % operator can return a fractional value. So 5.2 Mod 2 evaluates to 1 in VBScript, but 5.2 % 2 evaluates to 1.2 in Java.
Edit: Based on your edit, this appears to be the Luhn algorithm. The only real problem with the Java code is a typo; nothing to do with the mod operator. Here you assign a variable currrentNumber (with a triple R):
currrentNumber = Integer.valueOf(currentNumberString);
Then you use a different variable (double R):
Integer ModNumber = currentNumber * 2;
Edit: Another difference is that because VBScript string indices start at 1, and Java string indices start at 0, the code is using different alternate digits. Either If (i mod 2) <> 0 should be If (i mod 2) = 0, or if (i % 2 != 0) should be if (i % 2 == 0), I'm not sure which.

Java Integer digit reader

I am creating a method that needs to read a 5 digit integer digit by digit. (ie 26505 would be read as 2 6 5 0 5, and each digit could be read individually in another method) I cannot convert the integer to a string and read each character because I need the digits to be read by another method. It has also been suggested to use %10 but that wouldnt give me individual digits. Also, the integer needs to be read digit by digit from the left to right. I hope this is clear enough, but I am really confused on how to complete this and everything I have tried does not work. Any help offered would be appreciated, thank you.
while(d>=10){
j=code%d;
d=d/10;
printDigit(j)
This will return an array with the integer digits in order.
public static int[] integerToDigits(int n)
{
int[] digits= new int[5];
int temp = n;
for(int i = 0; i < 5; i++)
{
digits[4-i] = temp % 10;
temp /= 10;
}
return digits;
}
integerToDigits(12345) = {1,2,3,4,5}
For getting single digits from left-to-right: -
26505 / 10000 = 2
26505 % 10000 = 6505
6505 / 1000 = 6
6505 % 1000 = 505
505 / 100 = 5
505 % 100 = 5
5 / 10 = 5
I think you can now implement it.
But, if you are OK with traversing from right-to-left, it would be easier, since then your denominator will be fixed to 10: -
26505 % 10 = 5
26505 / 10 = 2650
2650 % 10 = 0
2650 / 10 = 265
265 % 10 = 5
265 / 10 = 26
26 % 10 = 6
26 / 10 = 2
2 % 10 = 2
Something totally lazy would look like
final int [] digits = {score % 1000 / 100, score % 100 / 10, score % 10};
which would work if you know your ints will never be larger than 999, for example.
From this example, it is trivial to improve it to support arbitrary integers by calculating the next power of ten from your integer and then adding digits to the array in a loop.
You can do this:
you can create a integer array and parse the each character of the user input string into and store into an array
then you can use this array for your other method.
e.g.
Scanner scan = new Scanner(System.in);
String str = scan.nextLine();
int[] digitArray = new int[str.length()];
for(int i=0; i<str.length(); i++)
{
String temp = Character.toString(str.charAt(i));
System.out.println("temp is "+temp);
digitArray[i] = Integer.parseInt(temp);
}
for (int i =0; i<digitArray.length; i++) {
System.out.println(digitArray[i]);
}

how to find 2 to the power of n . n ranges from 0 to 200

Assume my system as 32 bit machine. Considering this if I use long int for n>63 I will get my value as 0. How to solve it?
double is perfectly capable of storing powers of two up to 1023 exactly. Don't let someone tell you that floating point numbers are somehow always inexact. This is a special case where they aren't!
double x = 1.0;
for (int n = 0; n <= 200; ++n)
{
printf("2^%d = %.0f\n", n, x);
x *= 2.0;
}
Some output of the program:
2^0 = 1
2^1 = 2
2^2 = 4
2^3 = 8
2^4 = 16
...
2^196 = 100433627766186892221372630771322662657637687111424552206336
2^197 = 200867255532373784442745261542645325315275374222849104412672
2^198 = 401734511064747568885490523085290650630550748445698208825344
2^199 = 803469022129495137770981046170581301261101496891396417650688
2^200 = 1606938044258990275541962092341162602522202993782792835301376
Just wait around for a 256-bit compiler, then use int :-)
No, seriously, since you just want to start with 1 and keep doubling, your best bet is to get a big integer library like GNU MP.
You would do that with a piece of code like (untested):
#include <stdio.h>
#include "gmp.h"
int main (void) {
int i;
mpz_t num;
mpz_init_set_ui (num, 1);
for (i = 0; i <= 200; i++) {
printf ("2^%d = ", i);
mpz_out_str (NULL, 10, num);
printf ("\n");
mpz_mul_ui (num, num, 2);
}
return 0;
}
You could code up your own data structure of an array of longs with only two operations, double and print but I think it would be far easier to just use GMP.
If you do want to roll your own, have a look at this. It's a variation/simplification of some big integer libraries I've developed in the past:
#include <stdio.h>
#include <stdlib.h>
// Use 16-bit integer for maximum portability. You could adjust
// these values for larger (or smaller) data types. SZ is the
// number of segments in a number, ROLLOVER is the maximum
// value of a segment plus one (need to be less than the
// maximum value of your datatype divided by two. WIDTH is
// the width for printing (number of "0" characters in
// ROLLOVER).
#define SZ 20
#define ROLLOVER 10000
#define WIDTH 4
typedef struct {
int data[SZ];
} tNum;
// Create a number based on an integer. It allocates the segments
// then initialises all to zero except the last - that one is
// set to the passed-in integer.
static tNum *tNumCreate (int val) {
int i;
tNum *num = malloc (sizeof (tNum));
if (num == NULL) {
printf ("MEMORY ERROR\n");
exit (1);
}
for (i = 0; i < SZ - 1; i++) {
num->data[i] = 0;
}
num->data[SZ-1] = val;
}
// Destroy the number. Simple free operation.
static void tNumDestroy (tNum *num) {
free (num);
}
// Print the number. Ignores segments until the first non-zero
// one then prints it normally. All following segments are
// padded with zeros on the left to ensure number is correct.
// If no segments were printed, the number is zero so we just
// output "0". Then, no matter what, we output newline.
static void tNumPrint (tNum *num) {
int i, first;
for (first = 1, i = 0; i < SZ; i++) {
if (first) {
if (num->data[i] != 0) {
printf ("%d", num->data[i]);
first = 0;
}
} else {
printf ("%0*d", WIDTH, num->data[i]);
}
}
if (first) {
printf ("0");
}
printf ("\n");
}
// Double a number. Simplified form of add with carry. Carry is
// initialised to zero then we work with the segments from right
// to left. We double each one and add the current carry. If
// there's overflow, we adjust for it and set carry to 1, else
// carry is set to 0. If there's carry at the end, then we have
// arithmetic overflow.
static void tNumDouble (tNum *num) {
int i, carry;
for (carry = 0, i = SZ - 1; i >= 0; i--) {
num->data[i] = num->data[i] * 2 + carry;
if (num->data[i] >= ROLLOVER) {
num->data[i] -= ROLLOVER;
carry = 1;
} else {
carry = 0;
}
}
if (carry == 1) {
printf ("OVERFLOW ERROR\n");
exit (1);
}
}
// Test program to output all powers of 2^n where n is in
// the range 0 to 200 inclusive.
int main (void) {
int i;
tNum *num = tNumCreate (1);
printf ("2^ 0 = ");
tNumPrint (num);
for (i = 1; i <= 200; i++) {
tNumDouble (num);
printf ("2^%3d = ", i);
tNumPrint (num);
}
tNumDestroy (num);
return 0;
}
and its associated output:
2^ 0 = 1
2^ 1 = 2
2^ 2 = 4
2^ 3 = 8
2^ 4 = 16
2^ 5 = 32
2^ 6 = 64
2^ 7 = 128
2^ 8 = 256
2^ 9 = 512
: : : : :
2^191 = 3138550867693340381917894711603833208051177722232017256448
2^192 = 6277101735386680763835789423207666416102355444464034512896
2^193 = 12554203470773361527671578846415332832204710888928069025792
2^194 = 25108406941546723055343157692830665664409421777856138051584
2^195 = 50216813883093446110686315385661331328818843555712276103168
2^196 = 100433627766186892221372630771322662657637687111424552206336
2^197 = 200867255532373784442745261542645325315275374222849104412672
2^198 = 401734511064747568885490523085290650630550748445698208825344
2^199 = 803469022129495137770981046170581301261101496891396417650688
2^200 = 1606938044258990275541962092341162602522202993782792835301376
python supports big integers out of the box. At any linux prompt, run this:
$ python -c "for power in range(201): print power, 2**power"
0 1
1 2
2 4
3 8
4 16
5 32
6 64
<snip>
196 100433627766186892221372630771322662657637687111424552206336
197 200867255532373784442745261542645325315275374222849104412672
198 401734511064747568885490523085290650630550748445698208825344
199 803469022129495137770981046170581301261101496891396417650688
200 1606938044258990275541962092341162602522202993782792835301376
This can be easily made into a script if necessary. See any python tutorial.
It's been ages since I've used Java seriously, but: BigInteger class? It has all the usual mathematical (multiply, pow) and bitwise (shiftLeft) operations.
Your tagging is a little confusing though, which language did you prefer?
Use java.math.BigInteger.shiftLeft.
for (int i = 0; i <= 200; i++) {
System.out.format("%d = %s%n", i, BigInteger.ONE.shiftLeft(i));
}
Excerpt of output:
0 = 1
1 = 2
2 = 4
3 = 8
4 = 16
:
197 = 200867255532373784442745261542645325315275374222849104412672
198 = 401734511064747568885490523085290650630550748445698208825344
199 = 803469022129495137770981046170581301261101496891396417650688
200 = 1606938044258990275541962092341162602522202993782792835301376
If BigInteger is unavailable, you can also just manually do the multiplication and store it in a String.
String s = "1";
for (int i = 0; i < 200; i++) {
StringBuilder sb = new StringBuilder();
int carry = 0;
for (char ch : s.toCharArray()) {
int d = Character.digit(ch, 10) * 2 + carry;
sb.append(d % 10);
carry = d / 10;
}
if (carry != 0) sb.append(carry);
s = sb.toString();
System.out.format("%d = %s%n", i + 1, sb.reverse());
}
(see full output)
In C/C++ I don't know of a standard way you can store integers that big, pax's solution is the rightway to go.
However for Java, you do have a way out, BigInteger
Use scheme!
1 => (expt 2 200)
1606938044258990275541962092341162602522202993782792835301376
in kotlin :
var x= readLine()!!.toInt()
var y=BigDecimal(1)
for (i in 1..x)
{
y *= BigDecimal(2)
}
println(DecimalFormat().format(y))
If unsigned long int is 64 bits then the largest value for 2^n that you can represent is 2^63 (i.e. n = 63):
unsigned long int x = (1UL << n); // n = 0..63

Categories