Results to two decimals using ST_Area - postgresql

I have performed ST_Area on a shapefile but the resulting numbers are VERY long. Need to reduce them to two decimals. This is the code so far:
SELECT mtn_name, ST_Area(geom) / 1000000 AS km2 FROM mountain ORDER BY 2 DESC;
This is what I get:
mtn_name KM2
character varying double precision
1 Monte del Pueblo de Jerez del Marquesado 6.9435657067528e-9
2 Monte de La Peza 6.113288075418532e-9
I tried ROUND() but it brings KM to 0.00

Since it is not simply possible to round a decimal value (Decimal Precision problem) you will not get a double value which is exactly 6.94e-9. It would be something like 6.9400000001e-9 after rounding.
You can do:
demos:db<>fiddle
If the exponent is always the same (in your example it is always e-9) you can round with a fixed value. With double values, this results in the problem described above.
SELECT
round(area * 10e8 * 100) / 100 / 10e8
FROM area_result
To avoid these precision problems, you can use numeric type
SELECT
round(area * 10e8 * 100)::numeric / 100 / 10e8
FROM area_result
If you have different exponents, you have to calculate the multiplicator first. According to this solution you can do:
For double output
SELECT
round(area / mul * 100) * mul / 100
FROM (
SELECT
area,
pow(10, floor(log10(area))) as mul
FROM area_result
) s
For numeric output
SELECT
round((area / mul) * 100)::numeric * mul / 100
FROM (
SELECT
area,
pow(10, floor(log10(area)))::numeric as mul
FROM area_result
) s
However, your exponential result is just a view of the values. This can vary from database tool to database tool. Internally they are not stored as the view. So, if you fetch these values, you will, in fact, get a value like 0.00000000694 and not 6.94e-9, which is just a textual representation.
If you want to ensure to get exactly this textual representation, you can use number formatting to_char() for this, which, of course, returns a type text, not a number anymore:
SELECT
to_char(area, '9.99EEEE')
FROM area_result

Related

Imprecise math in postgres using type field numeric?

Very strange issue I am noticing... This link says the numeric data type should be able to precisely handle 16383 digits after the decimal: https://www.postgresql.org/docs/10/datatype-numeric.html
So can someone plz explain to me why this function returns 9499.99999999999905:
(((60000::numeric / 50500 * 50500) - 50500) * (50500::numeric / 50500))::numeric
The correct answer is 9500.
When I use this function I get the right answer:
(((60000::numeric(20,11) / 50500 * 50500) - 50500) * (50500::numeric(20,11) / 50500))::numeric(20,11)
and this gives wrong answer:
(((60000::numeric(25,16) / 50500 * 50500) - 50500) * (50500::numeric(25,16) / 50500))::numeric(25,16) = 9499.9999999999990500
The odd thing is this same issue is happening on this website: https://web2.0calc.com/
if you paste the formula:
((60000.0000000 / 50500 * 50500) - 50500) * (50500.0000000 / 50500) = 9500.
But if I instead add an extra 0 to each of those:
((60000.00000000 / 50500 * 50500) - 50500) * (50500.00000000 / 50500) = 9499.99999999999999999999999999999999999999999999999999999999999905.
Even weirder, for both postgres and this website, if I break down the formula into two executions like this:
((60000.00000000 / 50500 * 50500) - 50500) = 9500
(50500.00000000 / 50500) = 1
9500 * 1 = 9500.
What the heck is going on here?
That you get the right answer with numeric(20,11) and the wrong one with numeric(25,16) is a coincidence: both will have rounding errors, because they calculate only to a limited precision, but in the first case the rounded result happens to be the correct one.
The same is the case for 60000.0000000 and 60000.00000000: they are interpreted as numeric values with different scale.
SELECT scale(60000.0000000), scale(60000.00000000);
scale | scale
-------+-------
7 | 8
(1 row
The only thing that is not obvious is why you get such a bad scale when you cast to numeric without any scale or precision.
The scale of 60000::numeric is 0, and 50500 is also converted to a numeric with scale 0. Now if you divide two numeric values, the resulting scale is calculated by the function select_div_scale, and a comment there clarifies the matter:
/*
* The result scale of a division isn't specified in any SQL standard. For
* PostgreSQL we select a result scale that will give at least
* NUMERIC_MIN_SIG_DIGITS significant digits, so that numeric gives a
* result no less accurate than float8; but use a scale not less than
* either input's display scale.
*/
NUMERIC_MIN_SIG_DIGITS has the value 16. The problem that this heuristic solves is that the scale of the division cannot be determined by looking at the scale of the arguments. So PostgreSQL chooses a value of 16, unless one of the arguments has a bigger scale. This avoids ending up with extremely large result values, unless someone explicitly asks for it.

Rounding to two decimal places is not working

I am trying to reduce the decimal places of my number to two. Unfortunately is not possible. For this reason I added some of my code, maybe you will see the mistake...
Update [dbo].[company$Line] SET
Amount = ROUND((SELECT RAND(1) * Amount),2),
...
SELECT * FROM [dbo].[company$Line]
Amount in db which I want to change:
0.00000000000000000000
1914.65000000000010000000
376.81999999999999000000
289.23000000000002000000
Result I get after executing the code:
0.00000000000000000000
1366.28000000000000000000
268.89999999999998000000
206.38999999999999000000
Result I want to get (or something like this):
0.00000000000000000000 or 0.00
1366.30000000000000000000 or 1366.30
268.99000000000000000000 or 268.99
206.49000000000000000000 or 206.49
RAND() returns float.
According to data type precedence the result of multiplying decimal and float is float, try:
ROUND(CAST(RAND(1) as decimal(28,12)) * Amount, 2)
this should do the trick.

Select only two decimal places without rounding up

I want to select only two decimal places without rounding up.
$d = 123000.1264
'{0:f2}' -f $d
Result: 123000,13, but I need the result 123000,12
Any ideas to solve this problem?
Thank you in advance!
[Math]::Truncate(123000.1264 * 100) / 100
does it.
123000.1264 * 100 = 12300012.64
[Math]::Truncate(12300012.64) = 12300012
12300012 / 100 = 123000.12
You should use the [decimal] type for numbers when you need to preserve the accuracy of the fractional part, e.g.
$d = [decimal]123000.1264
and then [Math]::Truncate will use its decimal overload to give a decimal, and a decimal divided by an integer (or a double) will give a decimal result.
Of course, there is more than one way to interpret "up": it could mean increase in value (3 > -5) or increase in magnitude (|-5| > |3|). If you need the former, then use [Math]::Floor (which converts -1.1 -> -2.0) instead of [Math]::Truncate (which converts -1.1 -> 1.0).

How to display quotient as a percentage

I am using Postgresql to generate a simple quotient of two fields " a / b " = -3 / 300 = -.01 or -1.00%. Instead it displays as zero. I've tried many variations of to_char with no success. How could I get "select -3/300 as quotient" to display the quotient in xxx.xxx% format? Thanks
To display with the percentage sign, you can use the following format. Don't forget to first multiply by 100.0 so 1) is it indeed a percentage and 2) as noted by #dhke the computation is done with floats, not integers.
select to_char(100.0*-3/300,'999D99%') a;
a
----------
-1.00%
(1 row)

TSQL Round() inconsistency?

The problem we have is reduced to the following two statements:
select convert(float, (convert(float,5741.61)/convert(float, 196.00)) * convert(float,14.00)) as unrounded, round(convert(float, (convert(float,5741.61)/convert(float, 196.00)) * convert(float,14.00)), 2) as roundedTo2dp
select convert(float, 410.115) as unrounded, ROUND( convert(float, 410.115), 2) as roundedTo2dp
The first statement uses floats to calculate a value of 410.115, and also that result with a round() to 2 decimal places. The rounded value comes out at 410.11.
The second statement uses the float value 410.115 and also rounds it to 2 decimal places. The rounded result comes out as 410.12.
Why is one rounding down and the other rounding up when the value being rounded it the same?
How can I get the first statement to round to 410.12?
EDIT: apologies for formatting -- stackoverflow isn't showing any formatting on this machine (very odd).
Decimals are better with precision than floats. If you changed up the float to be something like DECIMAL(18,2), you'll get what you are expecting and you don't need to call the round function anymore.
select convert(decimal(18,2), (convert(decimal(18,2),5741.61)/convert(decimal(18,2), 196.00)) * convert(decimal(18,2),14.00)) as unrounded, round(convert(decimal(18,2), (convert(decimal(18,2),5741.61)/convert(decimal(18,2), 196.00)) * convert(decimal(18,2),14.00)), 2) as roundedTo2dp
results in
unrounded roundedTo2dp
410.12 410.12
Link to the MSDN about decimals. http://msdn.microsoft.com/en-us/library/ms187746.aspx
Hope that helps...
The numbers are not equal:
SELECT CAST(convert(float, (convert(float,5741.61)/convert(float, 196.00)) * convert(float,14.00)) AS BINARY(8))
UNION ALL
SELECT CAST(convert(float, 410.115) AS BINARY(8)) as bin
----
0x4079A1D70A3D70A3
0x4079A1D70A3D70A4
'float' is an approximate number data type and hence not all values in the data type range can be represented exactly.
This is based on http://msdn.microsoft.com/en-us/library/ms173773.aspx.
I believe this is why there is rounding issue while using float values. You can never be 100% sure!
Ex.
Select round(convert(float, 1.5555), 2) --Gives 1.56
Select round(convert(float, 1.555), 2) --Gives 1.55!
With such a simple number there is difference in expected result while using float.