Float precision in Bigquery [duplicate] - google-bigquery

We don't have decimal data type in BigQuery now. So I have to use float
But
In Bigquery float division
0.029*50/100=0.014500000000000002
Although
0.021*50/100=0.0105
To round the value up
I have to use round(floatvalue*10000)/10000.
Is this the right way to deal with decimal data type now in BigQuery?

Depends on your coding preferences - for example you can just use simple ROUND(floatvalue, 4)
Depends on how exactly you need to round - up or down - you can respectively adjust expression
For example ROUND(floatvalue + 0.00005, 4)
See all rounding functions for BigQuery Standard SQL at below link
https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#rounding-functions

Note that this question deserves a different answer now.
The premise of the question is "We don't have decimal data type in BigQuery now."
But now we do: You can use NUMERIC:
SELECT CAST('0.029' AS NUMERIC)*50/100
# 0.0145
Just make your column is NUMERIC instead of FLOAT64, and you'll get the desired results.

Rounding up in most SQL dialects is not a built-in function unless you're fortunate enough to be rounding up to an integer. In this case, CEIL is a quick and reliable solution.
In the case of rounding decimals up, we can also leverage CEIL, albeit with a couple of additional steps.
The procedure:
Multiply your value to move the last decimal to the tenths position. Ex. 18.234 becomes 1823.4 by multiplying by 100. (n * 100)
Use CEIL() to round up to the nearest integer. In our example, CEIL(n) = 1824.
Divide this result by the same figure used in step 1. In our example, n / 100 = 18.24.
Simplifying these steps leaves us with the below logic:
SELECT CEIL(value * 100) / 100 as rounded_up;
The same logic can be used to round down using the FLOOR function as such:
FLOOR(value * 100) / 100 AS rounded_down;
Thanks to #Mureinik for this answer.

Related

How to use bigquery round up results to 4 digits after decimal point?

We don't have decimal data type in BigQuery now. So I have to use float
But
In Bigquery float division
0.029*50/100=0.014500000000000002
Although
0.021*50/100=0.0105
To round the value up
I have to use round(floatvalue*10000)/10000.
Is this the right way to deal with decimal data type now in BigQuery?
Depends on your coding preferences - for example you can just use simple ROUND(floatvalue, 4)
Depends on how exactly you need to round - up or down - you can respectively adjust expression
For example ROUND(floatvalue + 0.00005, 4)
See all rounding functions for BigQuery Standard SQL at below link
https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#rounding-functions
Note that this question deserves a different answer now.
The premise of the question is "We don't have decimal data type in BigQuery now."
But now we do: You can use NUMERIC:
SELECT CAST('0.029' AS NUMERIC)*50/100
# 0.0145
Just make your column is NUMERIC instead of FLOAT64, and you'll get the desired results.
Rounding up in most SQL dialects is not a built-in function unless you're fortunate enough to be rounding up to an integer. In this case, CEIL is a quick and reliable solution.
In the case of rounding decimals up, we can also leverage CEIL, albeit with a couple of additional steps.
The procedure:
Multiply your value to move the last decimal to the tenths position. Ex. 18.234 becomes 1823.4 by multiplying by 100. (n * 100)
Use CEIL() to round up to the nearest integer. In our example, CEIL(n) = 1824.
Divide this result by the same figure used in step 1. In our example, n / 100 = 18.24.
Simplifying these steps leaves us with the below logic:
SELECT CEIL(value * 100) / 100 as rounded_up;
The same logic can be used to round down using the FLOOR function as such:
FLOOR(value * 100) / 100 AS rounded_down;
Thanks to #Mureinik for this answer.

postgresql round division

I want to divide values and round them up to 8 decimal places but i found that some divisions return in scientific notation.
How can i always get round division without scientific notation?
select round( 123/100000000::decimal, 8 )
returns 0.00000123 as expected.
select round( 1/100000000::decimal, 8 )
returns 1e-8 but... i was expecting 0.00000001
How can i round 1/100000000 to 8 decimal places and return 0.00000001 ?
sql fiddle: http://sqlfiddle.com/#!15/9eecb7db59d16c80417c72d1e1f4fbf1/1534
Thanks for help.
best,
Actually, when I try your code in Postgres 9.3.4 using pgAdmin, both return the values you want. The values are not in exponential notation. Hence, I suspect this is an issue with your application, not the database.
An easy way to check is to put the value as a string:
select round( 1/100000000::decimal, 8 )::text
This should not return exponential notation.
Probably second case go beyond precision range 8.
You can check this Question Selecting floating point numbers in decimal form
Also what version are you working with because in pgAdmin 9.2 I get a different result

Strange behavior while rounding in SQL server 2008

At some point I have a numeric(28,10) and I cast it in money (I know its bad but for legacy reason I have to return money) in the same time I also have to set the sign (multiplying by +1/-1).
In a first attempt I had cast the +/-1 to match the numeric type.
For the value 133.3481497944 we encounter a strange behavior (I have simplified the actual code in order to keep only the elements needed to demonstrate the problem):
SELECT CAST(CAST(133.3481497944 AS numeric(28,10))*cast(1 AS numeric(28,10)) AS money)
133.3482
which is not correctly rounded...
Removing the cast solve the problem
SELECT CAST(CAST(133.3481497944 AS numeric(28,10)) * 1 AS money)
133.3481
Did someone know what is happening in SQL? How can a multiplication by 1 and cast(1 AS numeric(28,10)) affect the result of the rounding?
When multiplying numerics, SQL uses the following rules to determine the precision and scale of the output:
p = p1 + p2 + 1
s = s1 + s2
which makes sense - you wouldn't want 1.5 * 2.5 to be truncated to one digit past the decimal. Nor would you want 101 * 201 to be limited to 3 digits of precision, giving you 20300 instead of 20301.
In your case that would result in a precision of 57 and a scale of 20, which isn't possible - the maximum precision and scale is 38.
If the resulting type is too big, decimal digits are sacrificed in order to preserve the integral (most significant) part of the result.
From the SQL Programmability & API Development Team Blog:
In SQL Server 2005 RTM (and previous versions), we decided preserve a minimum scale of 6 in both multiplication and division.
So your answer depands on how big and precise you need the multiplier to be. In order to preserve 10 digits of decimal precision. If the multiplier needs a scale bigger than 9, then decimal digits may be truncated. If you use a smaller precision and scale, you should be fine:
SELECT CAST(CAST(133.3481497944 AS numeric(28,10))*cast(1 AS numeric(9,7)) AS money)
yields 133.3481.
I don't see any ROUNDing here. I only see casting. Don't assume that it will round, when you CAST. Historically, when we cast the environment truncates (SQL server or not) or behaves not as we expect - especially when we're talking about FLOATs.
SELECT
CAST(CAST(133.3481497944 AS numeric(28,10))*cast(1 AS numeric(28,10)) AS money) --Your original,
CAST(1 AS numeric(28,10)) --Just the 1 casted,
CAST(133.3481497944 AS numeric(28,10)) --Your expected calculation,
CAST(133.3481497944 AS numeric(28,10))*cast(1 AS numeric(28,10)) -- The actual calculation
SELECT
CAST(133.3481497944 AS numeric(28,10))*cast(1.5 AS numeric(28,10)),
CAST(133.3481497944 AS numeric(28,10))*1.5,
CAST((133.3481497944*1) AS money),
133.3481497944*1
Returns
133.3482
1.0000000000
133.3481497944
133.348150
200.022225
200.02222469160
133.3481
133.3481497944
So as mentioned above, there really isn't any true rounding, but a loss of precision during the cast. As to exactly why, I don't know. Most likely during the calculation(multiplication) while using the Numeric(28,10) it cuts off some precision.
I added the second lines to show that really you may not need your numeric casting.

Math in SQL query not working

I have a sql query (SQL server 2005) that's creating a var and doing some math. The math works when the ticket count is 0 or 250000, but it's not creating a decimal point when the ticket count is any other value. (It reads 0.) Here is the query -
SELECT ticketCount, ((250000 - ticketCount) / 250000) * 100 AS percentSold
FROM raffleTickets
Where ticketCount in the DB is how many tickets of 250000 remain to be sold. If ticketCount is 250000, percentsold is 0, which is correct. If ticketCount is 0, percentSold is 100, which is correct. For all other values, percentSold is returning 0.
Please help! Thanks.
SQL Server does integer division (this varies among databases).
You can easily fix this by putting a decimal point after the constants:
SELECT ticketCount, ((250000.0 - ticketCount) / 250000.0) * 100.0 AS percentSold
FROM raffleTickets;
If you want the integer portion, then you can cast() the result back to an integer. Alternatively, you can use the str() function to convert the value of percentSold to a string with the appropriate number of decimal points.
Your formula is correct,
PercentSold = (TotalTickets - TicketsRemaining) / TotalTickets
But what is the Domain and Range of the above function? Your numbers are all expressed as integer, but you probably want to calculate using Real.
PercentSold = ( ( TotalTickets - TicketsRemaining )*100.0) / (TotalTickets)
This forces the calculation to be done in Real. Languages that know how to declare variables and calculations in specific types (i.e. Domains) can make this clearer, more apparent.
Wanting to represent a real number with a certain precision means you want to perform output formatting. SqlServer must have a way to specify output format for numbers in the Real Domain. I defer to SqlZoo.net for their answer to formatting.
The only thing you need to do is putting plus or minus 0.0 in your formula.
SELECT ticketCount, ((250000 - ticketCount - 0.0) / 250000) * 100 AS percentSold
FROM raffleTickets

Oracle ceil for decimal numbers

When rounding up to 2 decimal places, the value 4.01132141 would be rounded to 4.02 because it exceeds 4.01.
How can you do this in PL/SQL?
One way would be to do ceil(value*100)/100, but that seems inelegant. Not sure there's any way to make round behave the way you want.
The function to 'round up' is CEIL, but it generates an integer.
The function to 'round down' is FLOOR, but it too generates an integer.
The function to 'round nearest' is ROUND, and it allows you to specify a number of decimal places (dp).
Note that CEIL rounds to an integer; to round to 2 dp, you'd have to multiply by 100, use CEIL, and divide by 100.
To get the answer reasonably directly, use:
ROUND(value+0.005, 2)
This works because, for the example data of 4.01132141, the value passed to ROUND is 4.01632, and when rounded to 2 dp, that becomes 4.02. If the value started as 4.0593, say, then the value passed to ROUND would be 4.0643, which when rounded to 2 dp becomes 4.06, as required.
There are a couple of tricky bits there:
If the number of dp varies, the value to be added (0.005 in the example) varies. You could create a table to hold the number of decimal places in one column and the rounding value to add in the other. Alternatively, you could use an expression with powers of 10, etc.
Deciding on the correct behaviour for negative numbers. Does -4.01132141 become -4.02 or -4.01? You might need to play with SIGN and ABS functions to get that to work as you want.
I faced the same issue and came up with the following statement, it has worked fine so far.
select 4.01132141+(mod((ceil(4.01132141)-4.01132141)*1000,10)/1000) from dual
select 4.01132141, CEIL(4.01132141*100)/100 from dual
You can use this for Rounding up in PLSQL:
ROUND( UrNo+ (5 / POWER(10, DecimalPlaces + 1)) , DecimalPlaces)