有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java绑定此程序,以确定不包含零的倒数整数之和

A表示其十进制表示不包含数字0的正整数集。已知A中元素的倒数之和为23.10345

例1,2,3,4,5,6,7,8,9,11-19,21-29,31-39,41-49,51-59,61-69,71-79,81-89,91-99111-119

然后取每个数的倒数,求和

如何通过数字验证这一点

编写一个计算机程序来验证这个数字

以下是我到目前为止写的内容,我需要帮助解决这个问题,因为这个问题目前需要很长时间才能完成:

Java代码

import java.util.*; 

public class recip
{
    public static void main(String[] args)
    {
        int current = 0; double total = 0;

        while(total < 23.10245)
        {
            if(Integer.toString(current).contains("0"))
            {
                current++;
            }
            else
            {
                total = total + (1/(double)current);
                current++;
            }
            System.out.println("Total: " + total);
        }
    }
}

共 (3) 个答案

  1. # 1 楼答案

    如果处理得当,这并不难

    例如,假设您希望找到所有整数的倒数之和,从123开始(即最左边的数字),以k个非零数字结束。显然有9个这样的整数,每个整数的倒数在1/(124*10k)的范围内。。1/(123*10k)。因此,所有这些整数的倒数之和以(9/10)k/124和(9/10)k/123为界

    要找到从123开始的所有倒数之和的界限,必须将上面的界限与每k>=0.这是一个几何级数,因此可以推导出从123开始的整数的倒数和以10*(9/10)k/124和10*(9/10)k/123为界

    当然,同样的方法也适用于最左边数字的任何组合。 我们在左边检查的数字越多,结果就越准确。 下面是这种方法在python中的实现:

    def approx(t,k):
        """Returns a lower bound and an upper bound on the sum of reciprocals of
           positive integers starting with t not containing 0 in its decimal
           representation.
           k is the recursion depth of the search, i.e. we append k more digits
           to t, before approximating the sum. A larger k gives more accurate
           results, but takes longer."""
        if k == 0:
          return 10.0/(t+1), 10.0/t
        else:
            if t > 0:
                low, up = 1.0/t, 1.0/t
            else:
                low, up = 0, 0
            for i in range(10*t+1, 10*t+10):
                l,u = approx(i, k-1)
                low += l
                up += u
        return low, up
    

    例如,调用approx(0,8)可以得到下限和上限: 23.103447707... 和23.103448107。。。。 这与OP给出的索赔23.10345很接近

    有些方法收敛速度更快,但它们需要更多的数学知识。 可以在here中找到更好的和近似值。这个问题的一个推广是Kempner series

  2. # 2 楼答案

    对于带符号的32位整数,这个程序永远不会停止。它实际上会向-2097156收敛。由于有符号32位整数的最大谐波数(从1到N的整数倒数之和)是~14.66,因此即使电流从2^31 - 1-2^31时,该循环也不会终止。由于最大的负32位整数的倒数为~-4.6566e-10,因此每次电流返回到0,总和都将为负。假设double表示的最大数number + + 1/2^31 == number2^52/2^31,那么-2097156大约是收敛值

    话虽如此,假设你没有计算任意整数调和数的直接方法,你可以做一些事情来加速你的内部循环。首先,最昂贵的操作将是System.out.println;它必须与控制台交互,在这种情况下,程序最终必须将缓冲区刷新到控制台(如果有的话)。在某些情况下,这种情况可能不会真正发生,但由于您将其用于调试,因此它们与此问题无关

    然而,你也会花很多时间来确定一个数字是否为零。您可以翻转该测试以生成整数的范围,从而保证在该范围内不会有零位整数。这是非常简单的(增量地)(在C++中,但是微不足道地转换成java):

    class c_advance_to_next_non_zero_decimal
    {
    public:
        c_advance_to_next_non_zero_decimal(): next(0), max_set_digit_index(0)
        {
            std::fill_n(digits, digit_count, 0);
    
            return;
        }
    
        int advance_to_next_non_zero_decimal()
        {
            assert((next % 10) == 0);
    
            int offset= 1;
            digits[0]+= 1;
    
            for (int digit_index= 1, digit_value= 10; digit_index<=max_set_digit_index; ++digit_index, digit_value*= 10)
            {
                if (digits[digit_index]==0)
                {
                    digits[digit_index]= 1;
                    offset+= digit_value;
                }
            }
    
            next+= offset;
    
            return next;
        }
    
        int advance_to_next_zero_decimal()
        {
            assert((next % 10)!=0);
            assert(digits[0]==(next % 10));
    
            int offset= 10 - digits[0];
            digits[0]+= offset;
            assert(digits[0]==10);
    
            // propagate carries forward
            for (int digit_index= 0; digits[digit_index]==10 && digit_index<digit_count; ++digit_index)
            {
                digits[digit_index]= 0;
                digits[digit_index + 1]+= 1;
    
                max_set_digit_index= max(digit_index + 1, max_set_digit_index);
            }
    
            next+= offset;
            return next;
        }
    
    private:
        int next;
    
        static const size_t digit_count= 10; // log10(2**31)
    
        int max_set_digit_index;
    
        int digits[digit_count];
    };
    

    上面的代码所做的是迭代每个数字范围,使该范围只包含不带零的数字。它的工作原理是确定如何从N000开始。。。到N111。。。从N111开始。。。到(N+1)000。。。,携带(N+1)到1(0)000。。。如果必要的话

    在我的笔记本电脑上,我可以在8.73226秒内产生2^31-1的谐波数

  3. # 3 楼答案

    如何将当前数字存储为字节数组,其中每个数组元素都是数字0-9?这样,您可以非常快速地检测到零(使用==而不是String.contains来比较字节)

    缺点是您需要自己实现递增,而不是使用++。您还需要设计一种方法来标记“不存在”的数字,这样您就不会将它们检测为零。为不存在的数字存储-1听起来是一个合理的解决方案