妈的,我疯了!
http://www.palindromelist.net/palindromes-d/
单步示例:332是回文数吗?
n = 332
q = n / 10 = 33
r = n - 10 * q = 2
r > 0
r != q
n = q = 33
n > r
q = n / 10 = 3
r -= q = 4294967295
r *= 10 = 4294967286
r += n = 23
r != n
r != q
n = q = 3
n > r ? No, so 332 isn't a palindromic number.
溢出也不是问题。
两个除法是必要的,在代码 (C#) 中,它们通过乘法完成。
一个 n 位数字:~n/2 个分区!
const ulong c0 = 0xcccccccdUL;
static bool isPal(uint n)
{
if (n < 10) return true;
uint q = (uint)(c0 * n >> 35);
uint r = n - 10 * q;
if (r == 0) return false;
if (r == q) return true;
n = q;
while (n > r)
{
q = (uint)(c0 * n >> 35);
r -= q;
r *= 10;
r += n;
if (r == n || r == q) return true;
n = q;
}
return false;
}
using System;
class Program
{
static void Main() // take a break
{
uint n, c; var sw = System.Diagnostics.Stopwatch.StartNew();
n = ~0u; c = 0; sw.Restart(); while (n > 0) if (isPal0(n--)) c++;
Console.WriteLine(sw.Elapsed + " " + c); // 76 s
n = ~0u; c = 0; sw.Restart(); while (n > 0) if (isPal1(n--)) c++;
Console.WriteLine(sw.Elapsed + " " + c); // 42 s
n = ~0u; c = 0; sw.Restart(); while (n > 0) if (isPal2(n--)) c++;
Console.WriteLine(sw.Elapsed + " " + c); // 31 s
Console.Read();
}
static bool isPal0(uint u)
{
uint n = u, rev = 0;
while (n > 0) { uint dig = n % 10; rev = rev * 10 + dig; n /= 10; }
return u == rev;
}
static bool isPal1(uint u)
{
uint n = u, r = 0;
while (n >= 10) r = n + (r - (n /= 10)) * 10;
return u == 10 * r + n;
}
static bool isPal2(uint n)
{
if (n < 10) return true;
uint q = n / 10, r = n - 10 * q;
if (r == 0 || r == q) return r > 0;
while ((n = q) > r)
{
q /= 10; r -= q; r *= 10; r += n;
if (r == n || r == q) return true;
}
return false;
}
}
这个似乎更快。
using System;
class Program
{
static void Main()
{
uint n, c; var sw = System.Diagnostics.Stopwatch.StartNew();
n = ~0u; c = 0; sw.Restart(); while (n > 0) if (isPal(n--)) c++;
Console.WriteLine(sw.Elapsed + " " + c); // 21 s
Console.Read();
}
static bool isPal(uint n)
{
return n < 100 ? n < 10 || n % 11 == 0 :
n < 1000 ? /* */ n / 100 == n % 10 :
n < 10000 ? n % 11 == 0 && n / 1000 == n % 10 && isP(n) :
n < 100000 ? /* */ n / 10000 == n % 10 && isP(n) :
n < 1000000 ? n % 11 == 0 && n / 100000 == n % 10 && isP(n) :
n < 10000000 ? /* */ n / 1000000 == n % 10 && isP(n) :
n < 100000000 ? n % 11 == 0 && n / 10000000 == n % 10 && isP(n) :
n < 1000000000 ? /* */ n / 100000000 == n % 10 && isP(n) :
n % 11 == 0 && n / 1000000000 == n % 10 && isP(n);
}
static bool isP(uint n)
{
uint q = n / 10, r = n - 10 * q;
do { n = q; q /= 10; r -= q; r *= 10; r += n; } while (r < q);
return r == q || r == n;
}
}
使用几乎平衡的二叉搜索意大利面条树。
using System;
class Program
{
static void Main()
{
uint n, c; var sw = System.Diagnostics.Stopwatch.StartNew();
n = c = 0; sw.Restart(); while (n < ~0u) if (isPal(n++)) c++;
Console.WriteLine(sw.Elapsed + " " + c); // 17 s
Console.Read();
}
static bool isPal(uint n)
{
return n < 1000000 ? n < 10000 ? n < 1000 ? n < 100 ?
n < 10 || n % 11 == 0 : n / 100 == n % 10 :
n / 1000 == n % 10 && isP(n) : n < 100000 ?
n / 10000 == n % 10 && isP(n) :
n / 100000 == n % 10 && isP(n) :
n < 100000000 ? n < 10000000 ?
n / 1000000 == n % 10 && isP(n) :
n % 11 == 0 && n / 10000000 == n % 10 && isP(n) :
n < 1000000000 ? n / 100000000 == n % 10 && isP(n) :
n % 11 == 0 && n / 1000000000 == n % 10 && isP(n);
}
static bool isP(uint n)
{
uint q = n / 10, r = n - 10 * q;
do { n = q; q /= 10; r -= q; r *= 10; r += n; } while (r < q);
return r == q || r == n;
}
}
不平衡倒置。
using System;
class Program
{
static void Main()
{
uint n, c; var sw = System.Diagnostics.Stopwatch.StartNew();
n = c = 0; sw.Restart(); while (n < ~0u) if (isPal(n++)) c++;
Console.WriteLine(sw.Elapsed + " " + c); // 16 s
Console.Read();
}
static bool isPal(uint n)
{
return
n > 999999999 ? n % 11 == 0 && n / 1000000000 == n % 10 && isP(n) :
n > 99999999 ? n / 100000000 == n % 10 && isP(n) :
n > 9999999 ? n % 11 == 0 && n / 10000000 == n % 10 && isP(n) :
n > 999999 ? n / 1000000 == n % 10 && isP(n) :
n > 99999 ? n % 11 == 0 && n / 100000 == n % 10 && isP(n) :
n > 9999 ? n / 10000 == n % 10 && isP(n) :
n > 999 ? n % 11 == 0 && n / 1000 == n % 10 && isP(n) :
n > 99 ? n / 100 == n % 10 :
n < 10 || n % 11 == 0;
}
static bool isP(uint n)
{
uint q = n / 10, r = n - 10 * q;
do { n = q; q /= 10; r -= q; r *= 10; r += n; } while (r < q);
return r == q || r == n;
}
}