Precision of div in SQL - sql

select 15000000.0000000000000 / 6060802.6136561442650
gives 2.47491973525125848
How can I get 2.4749197352512584803724193507358?
Thanks a lot

You can't, because of the result rules for determining precision and scale. In fact, your scale is so large that there's no way to shift the result (ie, specifying no scale for the left operand).
First...
The decimal data type supports precision up to 38 digits
... but "precision" here means the total number of digits. Which, yes, your result should fit, but the engine won't shift things for you. The relevant rule is:
Operation Result precision Result scale *
e1 / e2 p1 - s1 + s2 + max(6, s1 + p2 + 1) max(6, s1 + p2 + 1)
* 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.
.... you're running afoul of the last note there. Here, let's run the numbers.
Your operands have precisions (total digits) of 21 and 20 (p1 and p2, respectively)
Your operands have scales (digits after the decimal) of 13 (s1 and s2)
So:
21 - 13 + 13 + max(6, 13 + 20 + 1) <- The bit in max is the scale, too
21 + max(6, 34)
21 + 34
= 55, with a scale of 34
... except 55 > 38. So the number of digits needs to be reduced. Which, because digits become less significant as the value gets smaller, are dropped from the scale (which also reduces the precision):
55 - 38 = 17 <- difference
55 - 17 = 38 <- final precision
34 - 17 = 17 <- final scale
Now, if we count the number of digits from the answer it gives you, .47491973525125848, you'll get 17 digits.

SQL Server can store decimal numbers with a maximum precision of 38.
SELECT CONVERT(decimal(38,37), 15000000.0000000000000 / 6060802.6136561442650)
AS TestValue brings 2.4749197352512584800000000000000000000.

If there is a pattern in the first parameter, you may save some precision with re-formulation such as
select 1000000 * (15 / 6060802.6136561442650)
I can't test it in sql-server, I have only Oracle available and I get
2,47491973525125848037241935073575410941

Related

Calculation issue in 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

SQL extra precision when calculating, why?

Do you know why SQL adds an extra precision when multiplying? example:
declare #x decimal(2,1) = 9.9;
Declare #y decimal(3,2) = 9.99;
--precision: p1 + p2 + 1 = 2 + 3 + 1 = 6
--scale: s1 + s2 = 1 + 2 = 3
declare #rM decimal(5,3) = #x * #y;--this is OK, why is the resulting precision 6 if 5 is OK?
Is there a scenario I am not aware of where multiplying two values needs 6 for precision?
SQL Server has detailed documentation on the precision and scale of numeric with various arithmetic operations.
For multiplication, this is:
e1 * e2 precision: p1 + p2 + 1 scale: s1 + s2
I think these conform to rules derived from arithmetic. The number of decimal places to the right of the decimal point is indeed s1 + s2 -- remember, scale is the number to the right. And I think the precision might be overstated by 1.
However, there might be some edge case where the extra decimal place is helpful.
Of course, the values are capped at the maximum scale and precision for a numeric/decimal value.

Euler Project 401 at Maxima

Statement of the problem:
The divisors of 6 are 1,2,3 and 6. The sum of the squares of these numbers is:
1 + 4 + 9 + 9 + 36 = 50
Allow sigma2(n) to represent the sum of the squares of the n-dividers.
Thus, sigma2(6) = 50.
And addition_sigma2 (n) is the sum of all sigma2, smaller than or equal to n. For example,
addition_sigma2(6) = 113
This is what I have programmed in Maxima:
sigma2(n) :=
divsum(n,2)$
addition_sigma2(n) :=
lreduce("+", makelist(sigma2(k), k, 1, n))$
But, it's very inefficient. Well, I need to calculate addition_sigma2(10^17) and my algorithm is not able to calculate it. Can you think of any improvements?

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.