我怀疑转换为字符串然后检查字符“0”是花费太长时间的步骤。如果你想避免全零,可能有助于增加current
:
(已编辑——感谢 Aaron McSmooth)
current++;
for( int i = 10000000; i >= 10; i = i / 10 )
{
if ( current % i ) == 0
{
current = current + ( i / 10 );
}
}
这是未经测试的,但概念应该很清楚:每当您达到 10 的幂的倍数(例如 300 或 20000),您添加下一个较低的 10 幂(在我们的示例中为 10 + 1 和 1000 + 100 + 10 + 1,分别),直到您的号码中不再有零。
相应地更改您的while
循环,看看如果您的问题变得可以管理,这是否对性能没有帮助。
哦,您可能还想System.out
稍微限制输出。每十分之一、百分之一或一万次迭代就足够了吗?
编辑第二个:
睡了一会儿,我怀疑我的回答可能有点短视(如果你愿意,请怪罪到晚了)。我只是希望,哦,一百万次迭代current
可以让你找到解决方案并将其留在那个地方,而不是使用log( current )
etc来计算更正案例。
再想一想,我发现整个问题有两个问题。一个是你的目标数字 23.10345 是一个符合我口味的 leeeeettle。毕竟,您正在添加数以千计的项目,如“1/17”、“1/11111”等,具有无限的十进制表示,它们加起来正好是 23.10345 的可能性很小。如果某个数值数学专家这么说,那很好——但是我想看看他们得出这个结论的算法。
另一个问题与第一个问题有关,涉及有理数的有限内存二进制表示。您可能会使用BigDecimals,但我有疑问。
因此,基本上,我建议您重新编程数值算法,而不是采用蛮力解决方案。对不起。
编辑第三个:
出于好奇,我用 C++ 编写了这个来测试我的理论。它现在运行了 6 分钟,大约为 14.5(大约 550 兆迭代)。走着瞧。
当前版本是
double total = 0;
long long current = 0, currPowerCeiling = 10, iteration = 0;
while( total < 23.01245 )
{
current++;
iteration++;
if( current >= currPowerCeiling )
currPowerCeiling *= 10;
for( long long power = currPowerCeiling; power >= 10; power = power / 10 )
{
if( ( current % power ) == 0 )
{
current = current + ( power / 10 );
}
}
total += ( 1.0 / current );
if( ! ( iteration % 1000000 ) )
std::cout << iteration / 1000000 << " Mio iterations: " << current << "\t -> " << total << std::endl;
}
std::cout << current << "\t" << total << std::endl;
手动计算currPowerCeiling
(或者人们可能称之为)可以节省一些log10
和pow
每次迭代的计算。每一点都有帮助 - 但它仍然需要永远......
编辑第四个:
状态约为 66,000 次 mio 迭代,总计高达 16.2583,运行时间约为 13 小时。看起来不太好,Bobby S.——我建议采用更数学的方法。