Ok I am having an issue trying to put a square root equation in a calculator. I am trying to figure out the expression builder. I know the expression builder takes the math operations of add, subtract, multiply, divide, equals and the parenthesis. What I am doing is trying to build the square root section. I have a simple Percent code to help with the square root.
In the Square root vs the Percent you see I am using binding. So here is the code for both.
On the square root is it possible to use the expression builder? I know there is no absolute formula for square root except for a number that is multipliable with itself like the number 4.
Sqrt(4) = 2
binding.btnSqrt.setOnClickListener {
var square = (tv_equation.text.toString().toDouble() / 2)
binding.tvResult.text = square.toString()
}
So in the event you a non square equation
sqrt(23) = 4.79
How would I simulate that as one function within the button. Can I use expression or would I need to use Kotlin.math
So between the two I divide by 100 on the percent. It works great.
binding.btnPercent.setOnClickListener {
var percentage = (tv_equation.text.toString().toDouble() / 100)
binding.tvResult.text = percentage.toString()
}
All my other buttons work fine and so I am just working on the square root before I can release this to google play.
You would need to use some form of a square root function.
AS you mentioned in your question Kotlin Sqrt Function is a very suitable choice
binding.btnSqrt.setOnClickListener {
if(!tv_equation.text.isNullOrEmpty){
var number = tv_equation.text.toString().toDouble()
binding.tvResult.text = sqrt(number).toString()
}
You can create a sqrt function using the Quake's first inverse square root.
Quake's first inverse square root.
Pseudo Code:
float InvSqrt(float x){
float xhalf = 0.5f * x;
int i = *(int*)&x; // store floating-point bits in integer
i = 0x5f3759df - (i >> 1); // initial guess for Newton's method
x = *(float*)&i; // convert new bits into float
x = x*(1.5f - xhalf*x*x); // One round of Newton's method
return x;
}
So the answer i want to add is a little more suitable with the previous answer. Maybe this will help some people in the future. This solution will also limit the decimal space to 4 decimals.
binding.btnSqrt.setOnClickListener{
val df = DecimalFormat("#.####")
if(!tv_equation.text.isNullOrEmpty())
{
val number = tv_equation.text.toString().toDouble()
binding.tvResult.text = df.format(sqrt(number))
}
}
you can adjust the val df = DecimalFormat("#.####") where the # to as many decimals as you would want.
Related
Background
I have an app in the Google Play store built in Kotlin.
It currently displays a grid that the user draws her password on.
Here's a snapshot of the grid as it was previously drawn with the previous default paint.strokeWidth.
The grey lines between the (red) posts are drawn with the following method:
private fun DrawGridLines() {
val paint = Paint()
for (y in 0..numOfCells) {
xCanvas!!.drawLine(
(0 + leftOffset).toFloat(), (y * cellSize + topOffset).toFloat(),
(numOfCells * cellSize + leftOffset).toFloat(),
(y * cellSize + topOffset).toFloat(), paint
)
}
for (x in 0..numOfCells) {
xCanvas!!.drawLine(
(x * cellSize + leftOffset).toFloat(), (0 + topOffset).toFloat(),
(x * cellSize + leftOffset).toFloat(), (numOfCells * cellSize + topOffset).toFloat(),
paint
)
}
}
The Problem
While working on updates to the app I ran it on the emulator and saw the following:
As you can see the gridlines are drawn properly. Very odd since it seems to be drawing partial grid lines. NOTE: I ran this on numerous API versions and they all draw the grid lines this way now.
paint.strokeWidth = 0.0
I added some code to examine the value of paint.strokeWidth but that is additionally odd. It shows that the value of strokeWidth is always 0.0.
You can see that in my logcat output:
The Fix
Yes, I can simply fix this by explicitly setting the value myself.
I added the following line of code to the routine above:
paint.strokeWidth = 5F;
Now it looks like the following:
However, I'd like to know why this has suddenly occurred??
I'd also like to know how it seems to draw "some" of the lines since the value of the strokeWidth is actually 0.0???
The first thing I see in your code is that nowhere the Paint gets configured or its strokeWidth assigned a value. You need to set specific values and not use defaults, as defaults don't take into consideration display densities neither may have a valid usable value at all.
In the next sniped of your code you instantiate a new Paint instance and use it straight away without setting any properties to it:
private fun DrawGridLines() {
val paint = Paint()
for (y in 0..numOfCells) {
xCanvas!!.drawLine(....
"Here using already the new paint??? where did you configure it?"
Secondly, notice that Paint.strokeWidth units are in pixels, therefore you need to take into account the device display density and adjust to it.
for example:
val DEFAULT_SIZE_PX = 5.0f
val scaledWidth = DEFAULT_SIZE_PX * context
.resources
.displayMetrics
.density
paint.strokeWidth = scaledWidth
Or, which is the same as:
val DEFAULT_SIZE_PX = 5.0f
val displayMetrics = context.resources.displayMetrics
val scaledWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_SIZE_PX, displayMetrics)
paint.strokeWidth = scaledWidth
The official docs on setStrokeWidth provides a very interesting statement:
"Hairlines always draw a single pixel..."
I suppose the way that is handled is now probably handled differently and has this type of effect on output now. Or it is related to the density issue.
Either way, it is odd that it has changed. And interesting/odd that it states that you can set it to 0 for hairline output.
Why can't I round correctly this:
val solution = Math. round(iDouble * 10.00) / 10.00
Debugger says:
iDouble = 118.64300000000001
solution = 118.6
I dont see what is wrong with that. Here is the explanantion.
118.64300000000001d * 10L = 1186.43d
Math.round will return the number rounded to the integer part as an long.
Math.round(1186.43d) = 1186L.
1186L / 10.00d = 118.6d
So it looks fine to me. Keep in mind that dividing by a double/float will result in a double/float.
Is it possible to get the x coordinate from a character in a TextView in Android?
I'm not looking for the coordinate of the TextView itself, I need the coordinate of the last character in the TextView (multi line)
Thanks in advance
Java Solution
Here is how to get the x and y coordinates of a specific character. offset is the index of the desired character in the textView's String. These coordinates are relative to the parent container
Layout layout = textView.getLayout();
if (layout == null) { // Layout may be null right after change to the text view
// Do nothing
}
int lineOfText = layout.getLineForOffset(offset);
int xCoordinate = (int) layout.getPrimaryHorizontal(offset);
int yCoordinate = layout.getLineTop(lineOfText);
Kotlin Extension Function
If you expect to use this more than once:
fun TextView.charLocation(offset: Int): Point? {
layout ?: return null // Layout may be null right after change to the text view
val lineOfText = layout.getLineForOffset(offset)
val xCoordinate = layout.getPrimaryHorizontal(offset).toInt()
val yCoordinate = layout.getLineTop(lineOfText)
return Point(xCoordinate, yCoordinate)
}
NOTE: To ensure layout is not null, you can call textview.post(() -> { /* get coordinates */ }) in Java or textview.post { /* get coordinates */ } in Kotlin
Use:
layout.getPrimaryHorizontal(int offset)
It is simple to use. You just iterate through the layout using the length of the text it uses.
It will return the x of the Character . So lines I'm still getting from the layout.getLineTop() . By the way, if you are using the layout.getLineTop() , note that there is some strange behaviour, possibly a bug.
Given a span that has one or more paragraphs, try to get the last character of the entire span dosen't work. Is there another way to get the same result of getPrimaryHorizontal()?
There all, i'm a newbie in android programming and i've a school task to analysis some project. So, i choose a Guitar Tuner project from github called pTune (link: here).
I've read the code and analyze it, from what i read and see there are a needle with an arc meter to see if the input sound (guitar voice) was fit.
In that project i want to display Toast if the tuning process are fit when the dial in 90 degree. So, i've add this Toast but its not displayed..
if (relativeFrequency == targetFrequency){
Toast.makeText(PTuneActivity.this, "FIT", Toast.LENGTH_SHORT).show();
}
That code placed in updateDisplay class, i've placed it in other class but still not work as i want.
public void updateDisplay(float frequency) {
// Calculate difference between target and measured frequency,
// given that the measured frequency can be a factor of target.
float difference = 0;
if (frequency > targetFrequency) {
int divisions = (int) (frequency / targetFrequency);
float modified = targetFrequency * (float) divisions;
if (frequency - modified > targetFrequency / 2) {
modified += targetFrequency;
divisions++;
}
difference = (frequency - modified) / (float) divisions;
} else {
// If target is greater than measured, just use difference.
difference = frequency - targetFrequency;
}
float relativeFrequency = targetFrequency + difference;
// Update TextView
if (relativeFrequency < 1000f)
t.setText(String.format("%.1f Hz", relativeFrequency));
else
t.setText(String.format("%.2f kHz", relativeFrequency/1000));
//My code
if (relativeFrequency == targetFrequency){
Toast.makeText(PTuneActivity.this, "FIT", Toast.LENGTH_SHORT).show();
}
// Update DialView
float value = difference / (targetFrequency / 2) * 90;
dial.update(value);
}
I know this is useless in real implementation but i want to learn android programming.
You're testing equality between 2 floats, one comes from an input ? It might never be exactly equal. You should add some log and an "else" statement to see if it goes inside the "if" because the Toast may not be the real problem
i've just try it by my self by digging and its worked for me, though its not good at all but i thinks ok, just add this line of code upper dial.update(value);
if (frequency >= targetFrequency) {
Toast.makeText(PTuneActivity.this, "FIT", Toast.LENGTH_SHORT).show();
}
As question title, I want to use the change values of accelerator at three axis x,y,z to test that device is standing still or is moving.
I can use titanium to get values of accelerator in 3 axis:
Ti.Accelerometer.addEventListenter('update',function(e))
{
var x=e.x;
var y=e.y;
var z=e.z;
var timestamp=e.timestamp;
}
In real device, those values change continuously. I want to calculate the change between two times update consecutive. But I need some pointers on how to do the calculation.
How about in addEventListener you keep 3 static variables or a single static structure containing the last values and calculate the abs() difference on them and the current values?
Pseudo code ( handling just one variable - expand to three ):
int f( int x )
{
static int old_x = -1;
if( x != old_x )
{
// movement detected and do something
old_x = x;
}
else
{
// no movement
}
}
}
you can use Ti.App.Properties variables to store values if you want. Instead of your pseudocode's c++ style static variable, use a property and update it at the end of your event listener.
http://developer.appcelerator.com/apidoc/mobile/1.8.2/Titanium.App.Properties-module