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?

有帮助吗?

解决方案

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

其他提示

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.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top