Post date: Jan 27, 2015 1:56:8 AM
"How many positive integers are a power of smaller integer, where the exponent is the same as the number of digits in the larger integer? For example, 8 ** 9 is nine digits."
The following rules allow us to limit our results, so we can be sure of getting every possible match.
We don't have to calculate 10 ** n, because 10 ** n is always equal to 1 plus n zeros, or n + 1 digits total. 11 ** n is the same, except even larger. So this puts a limit on the smaller integer.
Starting with n = 24, 9 ** n is only 23 digits. As n gets higher, the difference between n and the number of digits becomes greater. This limits n.
With these two things, we know that in the formula s ** n, s is between 1 and 9 and n is between 1 and 24.
; WITH Ten (i) AS
(
SELECT CONVERT(numeric(38,0), 1)
UNION ALL
SELECT CONVERT(numeric(38,0), i + 1)
FROM Ten
WHERE i < 9
),
TwentyFour (i) AS
(
SELECT 1
UNION ALL
SELECT i + 1
FROM TwentyFour
WHERE i < 24
)
SELECT COUNT(*)
FROM TwentyFour t24
CROSS JOIN Ten t10
WHERE LEN(POWER(t10.i,t24.i)) = t24.i
Alternate Answer
There is a flaw in the above answer. The POWER command returns a float that is accurate only to 12 digits. In this case, it doesn't hurt us; the answer is the same. But if we had to calculate numbers just slightly higher, this could have produced incorrect answers. The answer happens to be correct, but it was only luck that the particular numbers were within our safe range. We can't always count on being lucky.
So here is an answer that is safely accurate, even if the highest number had happened to be bigger. I will re-implement the POWER function. It is definitely slower.
(If this weren't Stupid SQL Tricks, I'd use the CLR to add some accurate and quick math functionality to SQL Server. But that's cheating.)
CREATE FUNCTION dbo.IntegerPower(@input numeric(38,0), @power int)
RETURNS numeric(38,0)
AS
BEGIN
IF @power < 0 RETURN CAST('Nice try, clever boy, but I''m not implementing that.' AS int) -- Ugly hack ... you can't raise an error in a function, but this will blow the heck up.
IF @power = 0 RETURN 1
DECLARE @result numeric(38,0) = @input
WHILE @power > 1
BEGIN
SET @result = @result * @input
SET @power = @power - 1
END
RETURN @result
END
GO
; WITH Ten (i) AS
(
SELECT CONVERT(numeric(38,0), 1)
UNION ALL
SELECT CONVERT(numeric(38,0), i + 1)
FROM Ten
WHERE i < 9
),
TwentyFour (i) AS
(
SELECT 1
UNION ALL
SELECT i + 1
FROM TwentyFour
WHERE i < 24
)
SELECT COUNT(*)
FROM TwentyFour t24
CROSS JOIN Ten t10
WHERE LEN(dbo.IntegerPower(t10.i,t24.i)) = t24.i
GO
DROP FUNCTION dbo.IntegerPower
GO