Question

Using SQL Server 2008 R2 when I enter the following query:

SELECT CAST(POWER(2.0, 63.0) AS BIGINT);

Which yields the result:

9223372036854775800

However, using the Windows desktop calculator and raising 2 to the 63 yields:

9223372036854775807

Can someone please explain the difference -- or is there some internal conversion that SQL Server is doing? ... or am I missing something else?

Was it helpful?

Solution

The range of BIGINTin MS Sql Server is:

-2^63 (-9,223,372,036,854,775,808) to 2^63-1 (9,223,372,036,854,775,807)

And your calculator is giving you the wrong number, because 2^63 can't have an odd number for its right-most digit.

The POWER function in SQL Server (http://technet.microsoft.com/en-us/library/ms174276.aspx), returns the same type as its first argument.

The correct way to write this query is:

DECLARE @foo REAL = 2.0
SELECT CAST(POWER( @foo, 63.0 ) AS BIGINT)

By which, you will get Arithmetic overflow error converting expression to data type bigint. error message. And about the reason that's http://www.extremeoptimization.com/resources/Articles/FPDotNetConceptsAndFormats.aspx

And regarding the question of why POWER function is returning a wrong number? As @simonatrcl mentioned in his answer, there is arithmetic problems with floating-point numbers which sometimes result in invalid result. You can read about floating-point numbers and the problems with them here:

http://www.extremeoptimization.com/resources/Articles/FPDotNetConceptsAndFormats.aspx

You can also check the boundaries for integer types in MS Sql Server here: http://technet.microsoft.com/en-us/library/ms187745.aspx

OTHER TIPS

Power will be returning a FLOAT. Floating point numbers are not accurate beyond certain limits, and will drop a bit of accuracy (if you've ever has a negative 0 problem you'll know what I mean!).

That's what you're getting here...

As far as the calculator goes and tested on XP, Win7 and Win8.1: 2^63 = 9223372036854775808 (obviously)

As far as MSSQL goes: The upper limit of a BIGINT is defined as 2^63-1, meaning 1 less than 2^63 Now if you would like MSSQL to calculate that for you one would be tempted to write something like:

SELECT POWER(CAST(2 AS BIGINT), 63) - 1

The result would be a bigint because you've cast the first argument of the power to a bigint. MSSQL will first calculate the power and then subtract 1. However, since the result of the power would exceed the range of a bigint, this statement will fail: Arithmetic overflow error converting expression to data type bigint.

So let us invoke some math to solve this. I assume everyone agrees with

2^4 = 2 * 2 * 2 * 2 = 2 * (2^3) = 2^3 + 2^3

and thus

2^4-1 = 2 * 2 * 2 * 2 - 1 = 2 * (2^3) - 1 = 2^3 + 2^3 - 1

That's what we're going to make use of...

SELECT POWER(CAST(2 AS BIGINT), 62) + (POWER(CAST(2 AS BIGINT), 62) - 1)

This results in 9223372036854775807 which is indeed the upper limit of a bigint.

Note that the () around the subtraction is really needed. Otherwise the addition of the result of the two powers would be done first, again resulting in an overflow.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top