对于练习,我必须将Horner函数实现为递归方法,该方法是将任何数字系统转换为Decimal的公式,例如对于101101 2,它将为(((((((1·2 + 0)·2) + 1)·2)+1)·2 + 0)·2 +1 =45₁₀

现在,该方法获得两个参数,一个数字数组和一个数字系统,例如2。

现在,如果我要使用第三个参数作为“计数器”来遍历数组,那么我将没有问题,但是我无法弄清楚。我可以使用辅助方法,但是我尝试了许多不同的方法,但没有一种有效。也许我在想的比实际要复杂。有人可以给我小费以引导我朝正确的方向吗? ^^

最佳答案

我想以下代码可以满足您的要求:

public class Main {

    /**
     * Hepler method to convert codepoints ('digitCodePoints') into their decimal corresponding
     * number (to be used with {@link #horner(java.lang.String, java.lang.String) horner method})
     * depending on the alphabet ('alphabetCodePoints').
     * @param digitCodePoints the raw digits of the number (most significant digit first).
     * @param alphabetCodePoints the raw alphabet codepoints of the system (least significant codepoint first). For example "01" for binary.
     * @return
     */
    private static int[] toDigits(final int[] digitCodePoints,
                                  final int[] alphabetCodePoints) {
        final int[] result = new int[digitCodePoints.length];
        for (int d = 0; d < digitCodePoints.length; ++d) {

            //Find where is the digitCodePoints[d] located in alphabetCodePoints:
            int index = 0;
            while (digitCodePoints[d] != alphabetCodePoints[index]) //Will throw ArrayIndexOutOfBoundsException if the digitCodePoints[d] is not found in alphabetCodePoints.
                ++index;

            result[d] = index;
        }
        return result;
    }

    /**
     * Works on codepoints.
     * @param digits the codepoints' literal which stores the digits of the number.
     * @param alphabet the alphabet of the system for which the convertion will take place. For example "01" for binary. Least significant digit comes first.
     * @return the decimal value of the resulting number.
     */
    public static int horner(final String digits,
                             final String alphabet) {
        final int[] alphabetCPs = alphabet.codePoints().toArray();
        return horner(toDigits(digits.codePoints().toArray(), alphabetCPs), alphabetCPs.length);
    }

    public static int horner(final int[] digits,
                             final int system) {
        return horner(digits, 0, digits.length, system);
    }

    /**
     * Standard method for converting 'digits' to their decimal number by Horner's method.
     * @param digits the digits of each place (most significant digit first).
     * @param offset the offset of 'digits' where we should end recursing.
     * @param length the length of 'digits' starting at 'offset'.
     * @param system the system for the convertion. For example 2 for binary, 16 for hexadecimal, and so on.
     * @return the decimal value of the resulting number.
     */
    public static int horner(final int[] digits,
                             final int offset,
                             final int length,
                             final int system) {
        return horner(digits, offset, offset + length - 1, 1, system);
    }

    /**
     * Main recursive method.
     * @param digits the digits of each place (most significant digit first).
     * @param offset the offset of 'digits' where we should end recursing.
     * @param index the index in digits to calculate next.
     * @param step how 'fast' we are traversing the array 'digits'. Typically 1. This exists mainly to create a different method signature than {@link #horner(int[], int, int, int) this} method.
     * @param system the system for the convertion. For example 2 for binary, 16 for hexadecimal, and so on.
     * @return the decimal value of the resulting number.
     */
    private static int horner(final int[] digits,
                              final int offset,
                              final int index,
                              final int step,
                              final int system) {
        if (digits[index] >= system)
            throw new IllegalArgumentException("digits[" + index + "]==" + digits[index] + " does not belong to the system " + system + '.');
        return index - step < offset
               ? digits[index]
               : horner(digits, offset, /* here you can see the usage of 'step': */ index - step, step, system) * system + digits[index];
    }

    public static void main(final String[] args) {
        System.out.println(horner(   new int[]{1, 0, 1, 1}   ,    2   )); //11.
        System.out.println(horner(   new int[]{0xF, 0xF}     ,    16  )); //255.
        System.out.println(horner( /* the number: */ "ffff" , /* the alphabet: */ "0123456789abcdef" )); //65535.
    }
}


如果您在理解step参数的含义时遇到麻烦,请考虑使其始终等于1!这是遍历数组的速度。例如,值2表示仅考虑半个数字。它可能会使事情复杂一些,但是我创建它的目的是使主要递归方法的方法签名与其他方法不同。您只能使用最后一个Horner方法,将step替换为1。

无论如何,我为每种方法都嵌入了一些javadoc(注释),以帮助您了解我在做什么。主要实现是最后的horner方法。

07-27 22:54