Double # showing 0 on android - android

I'm embarrassed to ask this question, but after 45 minutes of not finding a solution I will resort to public humiliation.
I have a number that is being divided by another number and I'm storing that number in a double variable. The numbers are randomly generated, but debugging the app shows that both numbers are in fact being generated.
Lets just say the numbers are 476 & 733. I then take the numbers and divide them to get the percentage 476/733 = .64
I then print out the variable and it's always set to 0. I've tried using DecimalFormat and NumberFormat. No matter what I try though it always says the variable is 0. I know there is something simple that I'm missing, I just can't find it =/.

I imagine that you are trying to do something like this:
int x = 476;
int y = 733;
double result = x / y; // result == 0
The problem here is that you are performing integer division which gives the answer 0, and then afterwards converting the result to a double. You need to convert one or both of the numbers to floating point numbers before dividing. Here's one way to do that:
int x = 476;
int y = 733;
double result = ((double)x) / y;

I presume the 2 numbers that are being divided are "double" types?
Have you used debug mode to see the result of the division?

Related

Order of operations in Android/Kotlin

Could anyone explain to me why this code works:
if (questionList[currentIndex].answer == inputAnswer) {
correctAnswers += 1*100/questionList.size
percentage.text = "Правильно: $correctAnswers%"
and this one doesn't:
if (questionList[currentIndex].answer == inputAnswer) {
correctAnswers += 1/questionList.size*100
percentage.text = "Правильно: $correctAnswers%"
When I click a button, set up with the first bit of code, everything works fine and my textView gets updated, but when I change the order of operations, nothing happens (textView.text doesn't change it's value).
Am I missing something?
Thank you in advance!
When you do math with integers, fraction components are not preserved. Suppose the size of the question list is 10.
In your first block of code, you have
1 * 100 / 10
Operations are done from left to right, so after the first multiplication, you have
100 / 10
and that resolves to 10.
Now with your second block of code you have
1 / 10 * 100
The first division with floating point numbers would be 0.1, but with integers, since the fraction is not preserved, it evaluates to 0.
0 * 100
which resolves to 0. So it will always result in zero if the dividend is smaller than the divisor.
If you really want to present fractional numbers, you should use floating point numbers, and if you want the result to be an Int, use roundToInt() on the result. If you just use toInt(), it will just drop the fraction rather than rounding to the nearest integer.

how to increase float without strange number

so i tried to increase number with float, but sometime it comes strange number but i just want a number like 0.1, 0.2, until 5.0 but it sometime comes with strange number like 0.9000001
this is my code to increase the float
addRattingBtn.onClick {
quantity += 0.1f
if (quantity >= 5.0f) {
toast("maximum")
return#onClick
}
totalRatting(quantity.toBigDecimal())
}
i already convert it to BigDecimal but it still not work.
why this is happen? and how to make it right. please help
This is because the finite nonzero values of any floating-point value set can all be expressed in the form s · m · 2(e - N + 1), where s is +1 or -1, m is a positive integer less than 2N, and e is an integer between Emin = -(2K-1-2) and Emax = 2K-1-1, inclusive, and where N and K are parameters that depend on the value set. Hence, float values cannot accurately represent base 10 real numbers and as you go on adding them they loose the precision sometime and shows such results, you should be using big decimal for the precision.
For example:
BigDecimal number = new BigDecimal(0.1);
BigDecimal add = number.add(new BigDecimal(0.1));

How to displaying Float/Double in meaningful form in Android

I am trying to make a BMI application. When I run the application the BMI values are displayed in numeral form that I don't understand. I have tried both Float and Double type but results are same.
For example:
Height (m): 2
Weight (Kg): 100
BMI is displayed as : 2.0E-4 instead of 25
The part of the code that effects this is:
String editText1= height_field.getText().toString();
String editText2= weight_field.getText().toString();
try { // Parse string to int
double height = Double.parseDouble(editText1);
double weight = Double.parseDouble(editText2);
double bmi_result = (weight/(height*height));
String bmi_text = Double.toString(bmi_result);
display.setText(bmi_text);
System.out.println("OnClick: computeButton is clicked");
}
catch(NumberFormatException nfe) {
alert.show(); // Show error alert
To answer your original question, you should be using java.text.DecimalFormat, something like:
DecimalFormat formatter = new DecimalFormat("##.##");
display.setText(formatter.format(bmi_result));
Will force the result to be in the format of two digits followed by two decimal points, the table in the link above shows how to generate that.
However, since 2.0E-4 is 0.0002, I think Jon Skeet's comment is correct: You're doing your math operation wrong, since the value you're printing is a very small fraction of 25 :)
I'd recommend using Log.v() to print out your math operation before you actually do it, so you can see what the values of weight and height actually are, I highly doubt they're correctly set at what you described in the question.

Best algorithm performance in equating many values

i am developing an android application right now. and i got a problem with one important method in my app, because i can't make best algorithm to equate many inputs to many data.
Here's the scenario:
The method's input is a coordinates from override method onTouchEvent(), so the input will be so many when the screen is touched and the finger is moved on it.
i have to equate that so-many-coordinate to 24 values in array.
the values in array is a coordinate as well. So when the input has the same value as values in arrays, it scores a point.
here's the code that i used:
public void checkCoordinate(float x, float y){
int sensitivity = 30;
for(int z = 0; z < 24; z++){
if(x > (cxy[z][0]-sensivity) && x < (cxy[z][0]+sensivity) && y > (cxy[z][1]-sensivity) && y < (cxy[z][1]+sensivity)){
points += 1;
Log.i("CheckCoordinate", "Total Points = "+points);
}
}
i have 2 ways to equating it. one, using the algorithm above or, using 24 if to check every input. but i don't think that 2 ways is good in this case.
so i need your help if you had the same case as mine and you have solved that or you have a better or best solution please tell me.
thank you in advance. sorry if my english is bad.
With this being said, your generic idea is correct. The question is can it now be optimized somehow?
There are many methods we can potentially employ here. The trick is all in the way you arrange your data. In your current case, you are doing a center point with your sensitivity variable being your span. One could imagine the first optimization being instead of using a sensitivity that moves left right up and down from a center point, you could implement instead a top-left point with a span that only moves right and down from the top-left point. Your if statement would then become:
if(x > cxy[z][0] && x < (cxy[z][0]+sensivity) && y > cxy[z][1] && y < (cxy[z][1]+sensivity))
So what does this do for you:
This above optimization allows you to hold the same overall amount of data but get rid of 2 math operations per check. Considering that your input parameters are both floating points, this can save quite a bit of time.
If you are doing all pixel based operations, then that brings me to the next optimization. Do ALL calculation using integers instead of floating point, this will also heavily speed up your overall algorithm time.
a further optimization could now be, if you are willing to spend more RAM for better performance, you could instead of having 1 point per region, you could have a top-left and a bottom-right point for each region. This would make your if statement look something like the following:
if(x > tlxy[z][0] && x < brxy[z][0] && y > tlxy[z][1] && y < brxy[z][1])
where tlxy is the array of top-left points, brxy is the array of bottom-right points
and z is still the "region" you are checking against
How does this aid:
As you can see in the above if statement, this now has absolutely no explicit math operations. To support this algorithm, you need to be willing to spend 2 times the memory as the array cxy originally was.
Now within your loop, you are going through ALL 24 region points. If you KNOW FOR CERTAIN that none of your regions overlap, then a point can truly only fall in 1 region at a time. You can save some time on most x y input points by breaking out of the for loop at the point you also increment points. That would look as follows:
public void checkCoordinate(float x, float y){
for(int z = 0; z < 24; z++){
if(x > tlxy[z][0] && x < brxy[z][0] && y > tlxy[z][1] && y < brxy[z][1]){
points += 1;
break;
}
}
}
The above will ONLY WORK IFF you know for certain there are no overlapping regions (not even edges.
On final optimization I can see might have potential. Depending on what your regions look like, you could pre-separate all regions into quadrants. This way you can test the x point to be on the left or right hand of the screen, then test the y point to be in the top or bottom. If your regions distribution is fairly even, this could have the potential to cut your test time down by 4 as you would not only need to test the regions within a quadrant (if the given statistical distribution is what I said). In the worst case, all regions lie in a single quadrant and all points you test are in that quadrant in which case the problem from a complexity standpoint is no worse than what it was before. It simply adds a setup test on your input x and y.
I hope this gives you enough info to at least get started on your way!!!
For 24 values, this might be an overkill, but you might also want to consider using a plain-array hash table (with open addressing collision resolution):
For simplicity, let's say you use the y value to get the jump position (if regions are well separated vertically, this should decrease the number of checks). Presuming that your screen resolution is 600x800, you can divide y by 60 to get ~13 slots. If you are using a 8-bit table, that equals to ~18 items per slot (round(800/60)=13, round(255/13)=18).
To speed up calculations, you should keep everything round and simple, so you can get the slot number using:
int yi = (int)y;
// this is your "hash function". depending on your actual data,
// you might want to modify it to get a lesser chance of collisions
byte slot = (byte)((yi / 60) * 18);
Now that you have the slot index, simply jump to the hash table and check until there are no more items to check:
rectangle r;
int yi = (int)y;
for (byte slot=(byte)(yi / 26); slot < 256; slot++)
{
r = hashtable[slot];
// is this an empty slot?
if (r.brxy == 0)
break;
// perform exact check
if (r.left < x && x < r.right &&
r.top < y && y < r.bottom)
break;
}
Hash table needs to be created during init in a similar way: for each of your 24 regions, calculate its hash (slot) index. If the position in the hash table is occupied, simply increase by 1 until you find an empty spot. NOTE: will you will have to add each region to all overlapping slots. A simplest way would be to add it to slots s, s-1 and s+1.
Your loop currently does 12 lookups on average, while a hash-based approach performs a single hash calculation and should require only two or three lookups on average (hash tables are said to have O(1) complexity on average, presuming a good hash function).
Example
Your hashtable should ideally look something like:
hashtable[0]: rectangle(0, 0, 60, 60);
hashtable[1]: rectangle(20, 20, 80, 80);
hashtable[2]: (empty)
hashtable[3]: (empty)
...
// next slot starts at [18]
hashtable[18]: rectangle(20, 20, 80, 80); // this region is in slots 0 and 1
hashtable[19]: rectangle(30, 70, 90, 130);
hashtable[20]: rectangle(400, 70, 460, 130);
hashtable[21]: (empty)
...
So, if your touch point is (430, 100), calculation will continue as follows:
a) slot = (byte)((100/60) * 18) = 18;
b) check hashtable[18], overlapping? no
c) check hashtable[19], overlapping? no
c) check hashtable[20], overlapping? yes, found after 3 checks
Performance only depends on the chosen hash-function:
If you have many items with similar x coordinates, you might get many collisions in some slots: that is why it's important to choose a good hash function. If regions are fixed, you can even create a perfect hash.

ANDROID How to reduce String allocations

I've managed to get my allocations down to next to nothing using DDMS (great tool), this has drastically reduced my GCs to about 1 or 2 every 3 minutes. Still, I'm not happy because those usually cause a noticeable delay in the game (on some phones) when you interact with it.
Using DDMS, I know what the allocations are, they are Strings being converted from integers used to display game information to the HUD.
I'm basically doing this:
int playerScore = 20929;
String playerScoreText = Integer.toString(playerScore);
canvas.drawText(playerScoreText, xPos, yPos);
This happens once each frame update and the HUD system is modular so I plug things in when I need and this can cause 4 or 5 hud elements to allocate Strings and AbstractStringBuilders in DDMS.
Any way to reduce these further or eliminate all the String allocations and just reuse a String object?
Thanks,
Albert Pucciani
Reading your question reminded me of one of Robert Greens articles that I read quite some time ago. It discusses your problem almost identically. http://www.rbgrn.net/content/290-light-racer-20-days-32-33-getting-great-game-performance . Skip down to day 33 and start reading.
Remember the last int score and its string representation. On a new frame check if the score is the same. If the same, then no need to create a new string - just use the old one.
Here's what I've done in the past. This will eliminate string allocations.
I create a char[] of a size that will be at least as large as the maximum number of characters you will need to display on the screen. This means that you should select a maximum high score that is achievable in the game. The way you have it now let's you display a score as high as 2^31-1 which is insanely huge, it's not practical with respect to the game. Keep in mind, this is your game, so it's ok to limit the max score to something more reasonable in the context of the game. Pick a number that will virtually be impossible to achieve. Setting this limit will then set you up to be able to not have to muck around with converting large integers to String objects.
Here's what's required:
First, you need to be able to separate the digits in an integer and convert them to char without creating String objects. Let's say you want to convert the integer of 324 into three separate characters '3','2','4' to be placed in the text char[]. One way you can do this is by taking the value 324 and do a mod 10 to get the lowest digit. So 324%10 = 4. Then divide the value by ten and do another mod 10 to get the next digit. So (324/10)%10 = 2, and (324/100)%10 = 3.
int score = 324;
int firstPlaceInt = score%10; // firstPlace will equal 4
int tensPlaceInt = (score/10)%10; // tensPlace will equal 2
int hundresPlaceInt = (score/100)%10; // hundredsPlace will equal 3
You will have to do the above in a loop, but this expresses the idea of what you're trying to do here.
Next, with these digits you can then convert them to chars by referencing a character map. One way to do this is you can create this character map by making a char[] of size 10 and placing values 0 - 9 in indexes 0 - 9.
char[] charMap = {'0','1','2','3','4','5','6','7','8','9',};
So doing this:
int score = 324;
char firstPlace = charMap[score%10];
char tenslace = charMap[(score/10)%10];
char hundredsPlace = charMap[(score/100)%10];
Will create the chars you need for the 3 digits in score.
Now, after all that, I would limit the highest score to say 99,999 (or whatever makes sense in your game). This means the largest "string" I would need to display is "Score: xx,xxx". This would require a char[] (call it text for this example) of size 13. Initialize the first 7 characters with "Score: ", these will never need to change.
char[] text = new char[13];
text[0] = 'S';
text[1] = 'c';
text[2] = 'o';
text[3] = 'r';
text[4] = 'e';
text[5] = ':';
text[6] = ' ';
The next 6 will vary based on the score. Note, that you may not necessarily fill in all 6 of those remaining characters, therefore you need to create an int (call it scoreCount for this example) which will tell you how many characters in the text char[] are actually relevant to the current score in the game. Let's say I need to display "Score: 324", this only takes 10 chars out of the 13. Write the 3 chars for the score of 324 into char[7] to char[9], and set scoreCount to 10 to indicate the number of valid characters in the char[].
int scoreCount = 7;
text[9] = charMap[score%10]; // This is firstPlace
text[8] = charMap[(score/10)%10]; // This is tensPlace
text[7] = charMap[(score/100)%10]; // This is hundredsPlace
scoreCount = 10;
You will probably have to do the above in a loop, but this should express the general idea of what you're trying to do here.
After that, you can just use drawText (char[] text, int index, int count, float x, float y, Paint paint). index will be 0, and count will be scoreCount which indicates how many characters in text should be drawn. In the example above, it doens't matter what's in text[10] to text[12], it's considered invalid. You can continue to update text[] using the character map, and this should not create any objects.
I hope this helps. The code above isn't very robust, but I wrote it out as more of an expression of the ideas I'm trying to convey. You will have to create your own loops and manage the data properly within your code, but this sums up the mechanics of what needs to happen to avoid the use of Strings/StringBuilder/StringBuffer/etc.

Categories

Resources