spliting a decimal values to lower decimal in sql server - sql

How can i split a decimal value into two decimal values.
if the decimal number which has fractional part that is less than .50 or greater than .50 .it should split in such a way that first no should end with only .00 or .50. second value should contain the remaining factorial value.
ex. 19.97 should return 19.50 & 0.47
19.47 19.00 & 0.47

You can "floor" to the highest multiple of 0.5 by multiplying by 2, calling FLOOR, then dividing by 2. From there just subtract that from the original value to get the remainder.
DECLARE #test decimal(10,7)
SELECT #test =19.97
SELECT
FLOOR(#test * 2) / 2 AS base,
#test - FLOOR(#test * 2) / 2 AS fraction
or to reduce duplication
SELECT
base,
#test - base AS fraction
FROM ( SELECT FLOOR(#test * 2) / 2 AS base )

Declare #money money
Set #money = 19.97
Select convert(int,#money - (#money % 1)) as 'LeftPortion'
,convert(int, (#money % 1) * 100) as 'RightPortion'

Observe that doubling 0.5 gives 1, which is a whole number. This leads to a simple algorithm:
Double the number
Split it into a whole and a fractional parts by using floor(x) and x-floor(x)
Divide each part separately by 2 to give you the results that you need.
Let's take your numbers as an example:
19.97 * 2 = 39.94
Whole part = 39, fractional part = 0.94
Dividing each part by 2 individually, we get
39/2 = 19.50
0.94/2 = 0.47
19.47 * 2 = 38.94
Whole part = 38, fractional part = 0.94
Dividing each part by 2 individually, we get
38/2 = 19.00
0.94/2 = 0.47

You would need to look into the MODULO operator in SQL Server.
SELECT
19.97 as myDecVal ,
19.97 % 0.5 AS decGreaterThan50,/*should return 0.47*/
19.97- (19.97 % 0.5) as roundedToNearestZeroPoint5 /*should return 19.50*/;

Related

Filter numeric column containing a digit

Is there any way to filter rows of a table where a numeric column contains a digit using maths?
I mean, currently, I'm solving that using:
where cast(t.numeric_column as varchar(255)) like "%2%"
However, I would like to know if could be possible to filter apply numeric operations...
Any ideas?
You could use division plus the modulus, if you knew the range of possible numbers. For example, assuming all expected numbers were positive and less than 100,000, you could use:
SELECT *
FROM yourTable
WHERE numeric_column % 10 = 2 OR
(numeric_column / 10) % 10 = 2 OR
(numeric_column / 100) % 10 = 2 OR
(numeric_column / 1000) % 10 = 2 OR
(numeric_column / 10000) % 10 = 2;
Although the above is ugly and unwieldy, it might actually outperform your approach which requires a costly conversion to string.

How to convert number (price) in to multiples of 0.05 using AutoHotKey script?

I was automating a trading software using AHK script. During price submission the app does not accept in between values, say between 1.50 and 1.55. It only accepts multiples of 0.05 because its tick-size is 0.05 hence i have to do the price conversion using AHK script.
You can just use
Round(N / 0.05) * 0.05
Example
Round(1.53 / 0.05) * 0.05 ; Returns 1.55
Explanation
I'm going to explain with 0.01 because it's easier to visualize, but it applies to any number. The number to round is 1.234. Anything after 3 will need to be discarded in the rounding process.
If we divide the number 1.234 by 100, we get 123.4. Note how the period is after 3. So we can just use Round now.
After rounding, the number is 123. Now we just need to scale it back down by multiplying by 0.01, which results in 1.23.
Formatting
As 0x464e pointed out in the comments, due how floating-point numbers work, the result may be imprecise. So if you're going to convert them to strings, do so using Format("{:.2f}", number).
The 2 comes from the minimum number of decimal places needed to accurately represent any number multiple of 0.05. By the way, this can be calculated by using:
Ceil(Log(1 / 0.05)) ; Returns 2
The following AHK function Roundoff converts and returns the price in its nearest tick-size multiple.
Roundoff(price) ;round off to nearest 5 paisa value
{
price := Round(price, 2) ;ronded to 2 decimal places
priceNoDecimal := Floor(price)
decimalPart := price - priceNoDecimal
decimalPart := Floor( Round(decimalPart * 100, 2) )
numerator := Floor(decimalPart / 5)
remainder := Mod(decimalPart, 5)
if ( remainder > 2)
retval := (numerator * 5) + 5
if ( remainder < 3)
retval := (numerator * 5)
retval := Round(priceNoDecimal + (retval / 100), 2)
return retval
}

SQL round percent up to nearest .1

I have a columns of percentages and i want them to always round up to the nearest .1
for example
.005 --> .1
.11 --> .2
.3256 -->.4
.6797 -->.7
I am trying ceiling and floor, but they give me all whole numbers
I have tried this, but it still rounds as it normally would work
round(n * 10, 0) / 10 as [nearest 0.10]
You can always use ceiling() and arithmetic:
select ceiling(percentage * 10) / 10.0
round() function can be the easiest option available.
select round(1.02345443,2) from dual
where the 1st argument is the input number and the second digit is digits after decimal point.
Please refer to this official doc for more reference.
Another option, with modular arithmetic:
DECLARE #a DECIMAL(5,5) = 0.000005 --insert your number here
PRINT ROUND(#a, 1) + CASE WHEN #a % 0.1 < 0.05 AND #a % 0.1 > 0 THEN 0.1 ELSE 0 END
This tests to see if the remainder when divided by 0.1 is between 0 and 0.05 (meaning it rounded down), and adds 0.1 to the rounded value if so.

SQL server round down wit 0.5 step [duplicate]

I read all rounding functions of T-SQL like Round, Floor, and Ceil, but none of them has rounded down decimal numbers correctly for me.
I have 2 questions:
How to round down a decimal number (3.69 ==> 3.5)?
How to round up the last 3 digits of an integer (e.g. 142600 ==> 143000)?
1) select CAST(FLOOR(2 * 3.69) / 2 AS decimal(2, 1)) handles the first case - courtesy of an answer to a similar question on SQL Server Forums, which I adapted and quickly checked.
Note that if the numbers you are rounding to the nearest 0.5 could be bigger (e.g. 333.69 => 333.5), be sure to specify more decimal precision when you cast (e.g. select CAST(FLOOR(2 * 3.69) / 2 AS decimal(10, 1))), or you could get an overflow error:
Msg 8115, Level 16, State 8, Line 1
Arithmetic overflow error converting numeric to data type numeric.
Extra precision will not affect the bottom-line result (i.e. select CAST(FLOOR(2 * 3.69) / 2 AS decimal(10, 1)) and select CAST(FLOOR(2 * 3.69) / 2 AS decimal(2, 1)) both yield 3.5); but it is wasteful if the numbers you are rounding will always be smaller.
Online references with examples are available for T-SQL FLOOR, CAST, and decimal to help.
2) select ROUND(142600, -3) handles the second case.
A similar online reference is available for T-SQL ROUND.
As per #J0e3gan 's anwser, Sql Server's Round allows rounding to the nearest powers of 10 using the length parameter, where length is 10^(-length), e.g.
length = 0 : 10 ^ 0 = nearest 1
length = 3 : 10 ^ -3 = nearest .001
length = -3 : 10 ^ 3 = nearest 1000
etc
However, in general, with a simple 1-based rounding function - e.g. (Sql Round with Length=0) to round to an arbitrary value of "nearest N" - with the formula:
round(X / N) * N
e.g. nearest 100
select round(12345 / 100.0, 0) * 100.0 -- 12300
select round(-9876 / 100.0, 0) * 100.0 -- -9900
select round(-9849 / 100.0, 0) * 100.0 -- -9800
... Nearest 0.5
select round(5.123 / 0.5, 0) * 0.5 -- 5.000
select round(6.499 / 0.5, 0) * 0.5 -- 6.500
select round(-4.499 / 0.5, 0) * 0.5 -- -4.50
... Nearest 0.02
select round(5.123 / .02, 0) * .02 -- 5.12
select round(-9.871 / .02, 0) * .02 -- -9.88
etc
Remember that the type used for the divisors must be numeric / decimal or float.
The Oracle/PLSQL FLOOR function returns the largest integer value that is equal to or less than a number.
eg:
FLOOR(7.9)
Result: 7
FLOOR(30.29)
Result: 30
FLOOR(-7.9)
Result: -8

SQL Round Function

round(45.923,-1) gives a result of 50. Why is this? How it is calculated?
(sorry guys i was mistaken with earlier version of this question suggesting value was 46)
The SQL ROUND() function rounds a number to a precision...
For example:
round(45.65, 1) gives result = 45.7
round(45.65, -1) gives result = 50
because the precision in this case is calculated from the decimal point. If positive then it'll consider the right side number and round it upwards if it's >= 5, and if <=4 then round is downwards... and similarly if it's negative then the precision is calculated for the left hand side of decimal point... if it's >= 5
for example round(44.65, -1) gives 40
but round(45.65, -1) gives 50...
ROUND(748.58, -1) 750.00
the second parameter: Lenght, is the precision to which numeric_expression is to be rounded. length must be an expression of type tinyint, smallint, or int. When length is a positive number, numeric_expression is rounded to the number of decimal positions specified by length. When length is a negative number, numeric_expression is rounded on the left side of the decimal point, as specified by length.
From
It is expected to be 50.
round(45.923, 0) => 46
expl: the last non-decimal digit is rounded (5), the desicion is based on the next digit (9)
9 is in the high half, ergo 5 is rounded up to 6
round(45.923, 1) => 45.9
expl: the first decimal digit is rounded (9), the desicion is based on the next digit (2)
2 is in the low half, ergo 9 stays 9
your case:
round(45.923, 1-) => 45.92
expl: the secon-last non-decimal digit is rounded (4), the desicion is based on the next digit (5)
5 is in the top half, ergo 4 is rounded up to 5, the rest of the digist are filled with 0s
As for how, start by considering how you'd round a (positive) float to the nearest integer. Casting a float to an int truncates it. Adding 0.5 to a (positive) float will increment the integer portion precisely when we want to round up (when the decimal portion >= 0.5). This gives the following:
double round(double x) {
return (long long)(x + 0.5);
}
To add support for the precision parameter, note that (for e.g. round(123456.789, -3)) adding 500 and truncating in the thousands place is essentially the same as adding 0.5 and to rounding to the nearest integer, it's just that the decimal point is in a different position. To move the radix point around, we need left and right shift operations, which are equivalent to multiplying by the base raised to the shift amount. That is, 0x1234 >> 3 is the same as 0x1234 / 2**3 and 0x1234 * 2**-3 in base 2. In base 10:
123456.789 >> 3 == 123456.789 / 10**3 == 123456.789 * 10**-3 == 123.456789
For round(123456.789, -3), this means we can do the above multiplication to move the decimal point, add 0.5, truncate, then perform the opposite multiplication to move the decimal point back.
double round(double x, double p) {
return ((long long)((x * pow10(p))) + 0.5) * pow10(-p);
}
Rounding by adding 0.5 and truncating works fine for non-negative numbers, but it rounds the wrong way for negative numbers. There are a few solutions. If you have an efficient sign() function (which returns -1, 0 or 1, depending on whether a number is <0, ==0 or >0, respectively), you can:
double round(double x, double p) {
return ((long long)((x * pow10(p))) + sign(x) * 0.5) * pow10(-p);
}
If not, there's:
double round(double x, double p) {
if (x<0)
return - round(-x, p);
return ((long long)((x * pow10(p))) + 0.5) * pow10(-p);
}
It doesn't for me on MySQL:
mysql> select round(45.923,-1);
+------------------+
| round(45.923,-1) |
+------------------+
| 50 |
+------------------+
1 row in set (0.00 sec)
And on Sql Server 2005:
select round(45.923,-1)
------
50.000
What database are you running this on?
one thing is in the round function first parameter is the number and the second parameter is the precision index from the decimal side.
That means if precision index is 0 it is at the first decimal, -1 means before the decimal first number, 1 means right side of the first decimal i.e second decimal
For example
round(111.21,0)---------> return 111
round(115.21,-1)--------->return 120
round(111.325,2)---------->return 111.33
round(111.634,1)-----------> return 111.6