Calculation issue in Kotlin - kotlin

So i am just doing a simple calculation in my app but somehow I'm not getting expected answer with the formula.
var i = 90 / 60 * 1000
This always returns 1000 instead of 1500
It seems some issue with the floating point from 90 / 60 operation, but I'm not sure how to handle it in Kotlin.

The whole number (integer) division 90 / 60 results in 1, namely the places in front of the decimal point. Better divide by a floating point number:
var i = 90 / 60f * 1000
// result: 1500.0

Related

SQL Server : Decimal Precision/Scale are yielding strange results

I was working on a bit of SQL for a project, and I noticed some seemingly strange behavior in SQL Server, with regard to what the answer looks like when dividing with decimals.
Here are some examples which illustrate the behavior I'm seeing:
DECLARE #Ratio Decimal(38,16)
SET #Ratio = CAST(210 as Decimal(38,16))/CAST(222 as Decimal(38,16));
select #Ratio -- Results in 0.9459450000000000
DECLARE #Ratio Decimal(38,16)
SET #Ratio = CAST(210 as Decimal)/CAST(222 as Decimal);
select #Ratio -- Results in 0.9459459459459459
For the code above, the answer for the query which is (seemingly) less precise gives a more precise value as the answer. When I cast both the dividend and the divisor as Decimal(38,16), I get a number with a scale of 6 (casting it to a Decimal(38,16) again results in the 0's padding the scale).
When I cast the dividend and divisor to just a default Decimal, with no precision or scale set manually, I get the full 16 digits in the scale of my result.
Out of curiosity, I began experimenting more with it, using these queries:
select CAST(210 as Decimal(38,16))/CAST(222 as Decimal(38,16)) --0.945945
select CAST(210 as Decimal(28,16))/CAST(222 as Decimal(28,16)) --0.9459459459
select CAST(210 as Decimal(29,16))/CAST(222 as Decimal(29,16)) --0.945945945
As you can see, as I increase the precision, the scale of the answer appears to decrease. I can't see a correlation between the scale of the result vs the scale or precision of the dividend and divisor.
I found some other SO questions pointing to a place in the msdn documentation which states that the resulting precision and scale during an operation on a decimal is determined by performing a set of calculations on the precision and scale of the divisor and dividend, and that:
The result precision and scale have an absolute maximum of 38. When a result precision is greater than 38, the corresponding scale is reduced to prevent the integral part of a result from being truncated.
So I tried running through those equations myself to determine what the output of dividing a Decimal(38,16) into another Decimal(38,16) would look like, and according to what I found, I still should have gotten back a more precise number than I did.
So I'm either doing the math wrong, or there's something else going on here that I'm missing. I'd greatly appreciate any insight that any of you has to offer.
Thanks in advance...
The documentation is a little incomplete as to the magic of the value 6 and when to apply the max function, but here's a table of my findings, based on that documentation.
As it says, the formulas for division are:
Result precision = p1 - s1 + s2 + max(6, s1 + p2 + 1), Result scale = max(6, s1 + p2 + 1)
And, as you yourself highlight, we then have the footnote:
The result precision and scale have an absolute maximum of 38. When a result precision is greater than 38, the corresponding scale is reduced to prevent the integral part of a result from being truncated.
So, here's what I produced in my spreadsheet:
p1 s1 p2 s2 prInit srInit prOver prAdjusted srAdjusted
38 16 38 16 93 55 55 38 6
28 16 28 16 73 45 35 38 10
29 16 29 16 75 46 37 38 9
So, I'm using pr and sr to indicate the precision and scale of the result. The prInit and srInit formulas are exactly the forumlas from the documentation. As we can see, in all 3 cases, the precision of the result is vastly larger than 38 and so the footnote applies. prOver is just max(0,prInit - 38) - how much we have to adjust the precision by if the footnote applies. prAdjusted is just prInit - prOver. We can see in all three cases that the final precision of the result is 38.
If I apply the same adjustment factor to the scales then I would obtain results of 0, 10 and 9. But we can see that your result for the (38,16) case has a scale of 6. So I believe that that is where the max(6,... part of the documentation actually applies. So my final formula for srAdjusted is max(6,srInit-prOver) and now my final Adjusted values appear to match your results.
And, of course, if we consult the documentation for decimal, we can see that the default precision and scale, if you do not specify them, are (18,0), so here's the row for when you didn't specify precision and scale:
p1 s1 p2 s2 prInit srInit prOver prAdjusted srAdjusted
18 0 18 0 37 19 0 37 19

Orbital Mechanics: Estimated Time To Form Specific Angle Between Two Planets

I'm trying to come up with a formula to estimate reoccurring times when two orbiting planets will form a target angle. I've made some very important assumptions for the sake of simplicity:
Pretend Kepler's laws do not exist
Pretend the speeds are constant
Pretend both planets are orbiting along the same path
Pretend this path is a circle, NOT an ellipse
Here is a diagram to assist in understanding my challenge (Google Docs):
https://docs.google.com/drawings/d/1Z6ziYEKLgc_tlhvJrC93C91w2R9_IGisf5Z3bw_Cxsg/edit?usp=sharing
I ran a simulation and stored data in a spreadsheet (Google Docs):
https://docs.google.com/spreadsheet/ccc?key=0AgPx8CZl3CNAdGRRTlBUUFpnbGhOdnAwYmtTZWVoVVE&usp=sharing
Using the stored data from the simulation, I was able to determine a way to estimate the FIRST occurrence that two orbiting planets form a specific angle:
Initial State
Planet 1: position=0 degrees; speed=1 degree/day
Planet 2: position=30 degrees; speed=6 degrees/day
Target Angle: 90 degrees
I performed these steps:
Speed Difference: s2 - s1 ; 6 - 1 = 5 degrees / day
Angle Formed: p2 - p1 ; 30 - 0 = 30 degrees
Find Days Required
Target = Angle + (Speed Diff * Days)
Days (d) = (Target - Angle) / Speed Diff
90 = 30 + 5d
60 = 5d
d = 12 days
Prove:
Position of Planet 1: 0 + (1 * 12) = 12 degrees
Position of Planet 2: 30 + (6 * 12) = 30 + 72 + 102 degrees
Angle: 102 - 12 = 90 degrees
Using this logic, I then returned to an astronomy program that uses Astro's Swiss Ephemeris. The estimated days got me close enough to comfortably pinpoint the date and time when two planets reached the desired angle without affecting application performance.
Here is where my problem lies: Given the information that I know, what approach should I take in order to estimate re-occurring times when a 90 degree angle will be reached again?
Thank you for taking the time to read this in advance.
There is not a simple formula as such but there is an algorithm you could program to determine the results. Pentadecagon is also correct in that you need to take into account n*360. You are also right in that you stop one of the planets and work on the difference of the speeds.
After d days the difference in degrees between the planets is 30 + d*5.
Since we are only interested in degrees between 0 and 360 then the difference of the angle between planets is (30 + d*5) mod 360.
In case you do not know a mod b gives the remainder when a is divided by b and most programming languages have this operation built in (as do spreadsheets).
You have spotted you want the values of d when the difference is 90 degrees or 270 degrees
So you need to find the values of d whenever
(30 + d*5) mod 360 = 90 or (30 + d*5) mod 360 = 270
pseudo code algorithm
FOR (d=0; d<11; d=d+5)
IF((30 + d*5) MOD 360 = 90 OR (30 + d*5) MOD 360 = 270)
PRINT d
NEXT
The funny thing about angles is that there are different ways to represent the same angle. So you currently set
Target = 90
One revolution later, the same angle could be written as
Target = 90 + 360 = 450
Or generally, n revolutions later
Target = 90 + n * 360
If you also want the same angle with opposite orientation you can set
Target = -90 + n * 360
If you use solve your equation for each of those target angles, you will find all the events you are looking for.

Penny calculator mod division

I have an assignment for a beginners VB class, and I have looked for examples for a penny calculator and have read them and tried to figure out where I am going wrong. I have a text box that takes the number of pennies you want to figure out. If you input 101 pennies it comes back with 1 dollar and 1 penny.
Strangely it works for up to 137 pennies. That comes back with 1 dollar 1 quarter 1 dime 2 pennies. If it goes to 138 or higher it just screws up. If I input 138 I get 1 dollar, 2 quarters, 1 dime, 1 nickel, 3 pennies. If I use 17 I get 1 quarter, 2 dimes, 1 nickel, 2 pennies.
Here is the arithmetic portion of my code.
DolBack = intLeftOver / 100
intLeftOver = intLeftOver Mod 100
LblDolRes.Text = DolBack.ToString
QrtBack = intLeftOver / 25
intLeftOver = intLeftOver Mod 25
LblQrtRes.Text = QrtBack.ToString
DimBack = intLeftOver / 10
intLeftOver = intLeftOver Mod 10
LblDimRes.Text = DimBack.ToString
NicBack = intLeftOver / 5
intLeftOver = intLeftOver Mod 5
LblNicRes.Text = NicBack.ToString
PenBack = intLeftOver
LblPenRes.Text = PenBack.ToString
I have tried to look my code over and look at other examples, but apparently I'm doing it a little differently. If anyone could point out the apparent major flaw in my code or my way of doing it I would appreciate it.
Further clarifying I have looked at the post at
Penny Calculator
Obviously there are a few differences with the actual arithmetic. In the link given is that because that is the only way to do it without rounding issues?
there are 100 pennies in a dollar, 25 pennies in a quarter, 10 pennies in a dime, 5 pennies in a nickel.
EDIT: Thanks for the help and pointing out my error. It's appreciated.
You're right that it's a rounding error. Use
DolBack = intLeftOver \ 100
instead of
DolBack = intLeftOver / 100
(and the same for the other ones) and you'll see a very different result.
The reason is that the / operator will do floating point division, regardless of the values either side of it, so 38/25 will yield an answer of 1.52, which rounds upwards (as you suspected) when assigned back to the variable, which is defined as an Integer. On the other hand, the \ operator will do integer division, truncating rather than rounding.
The Math.DivRem method is helpful for this kind of problem.
Dim dollars As Integer
Dim fifty As Integer
Dim quarter As Integer
Dim dime As Integer
Dim nickel As Integer
Dim pennies As Integer = 137
dollars = Math.DivRem(pennies, 100, pennies)
fifty = Math.DivRem(pennies, 50, pennies)
quarter = Math.DivRem(pennies, 25, pennies)
dime = Math.DivRem(pennies, 10, pennies)
nickel = Math.DivRem(pennies, 5, pennies)

Time to turn 180 degrees

I have a space ship, and am wanting to calculate how long it takes to turn 180 degrees. This is my current code to turn the ship:
.msngFacingDegrees = .msngFacingDegrees + .ROTATION_RATE * TV.TimeElapsed
My current .ROTATION_RATE is 0.15, but it will change.
I have tried:
Math.Ceiling(.ROTATION_RATE * TV.TimeElapsed / 180)
But always get an answer of 1. Please help.
To explain why you get 1 all the time:
Math.Ceiling simply rounds up to the next integer, so your sum contents must always be < 1.
Rearranging your sum gives TV.TimeElapsed = 180 * (1/.ROTATION_Rate). With a ROTATION_Rate of 0.15 we know that TV.TimeElapsed needs to reach 1200 before your overall function returns > 1.
Is it possible that you're always looking at elapsed times less than this threshold?
Going further to suggest what your sum should be is harder - Its not completely clear without more context.

Simple maths in Objective-C producing unexpected results

I'm doing the following in Objective-C and expecting 180 as the output but I'm getting 150. Can anyone explain what I'm doing wrong?
(360 / 100) * 50
You're (accidentally) using integer division. 360 / 100 is returning 3, then 3 * 50 is of course 150. To obtain a floating point result, try casting 360 or 100 to a float first, or just use a literal float - i.e., 360.0 / 100 or 360 / 100.0 or even 360.0 / 100.0.
Or, as #KennyTM pointed out in a comment, you can reorder the statement such as 360 * 50 / 100 -- this is particularly useful if a floating-point number is unacceptable for any reason.