Что не так с модулем с двойным, чтобы найти цифры числа? - PullRequest
0 голосов
/ 01 декабря 2018

Я пытаюсь найти число цифр в длинном двойнике, которое не может содержать int.Он берет введенный пользователем номер, находит его цифры и помещает его в массив int.Кажется, что он отлично работает с меньшими числами, такими как <10 ^ 10, но когда он приближается к большим числам, последние несколько цифр, кажется, выключены.</p>

Посмотрите на мою функцию, пожалуйста:

static void insertDigits(int[] digits, double number) {
    double num=number;
    int counter=digits(number)-1;
    while(counter>=0) {
        digits[counter]=(int) (num%10);
        num=Math.floor(num/10);
        counter=counter-1;
    }
}

Когда я ввожу 13256709, я получаю (хорошо): 1.3256709E7 1 1.3256709E7 3 1.3256709E7 2 1.3256709E7 5 1.3256709E7 6 1.3256709Е7 7 1.3256709E7 0 1.3256709E7 9 Но когда я ввести длинный номер, такой как 25768437216701562, я получаю: 2.576843721670156E16 2 2.576843721670156E16 5 2.576843721670156E16 7 2.576843721670156E16 6 2.576843721670156E16 8 2.576843721670156E16 4 2.576843721670156E16 3 2.576843721670156E16 7 2.576843721670156E16 2 2,576843721670156E16 1 2.576843721670156E16 6 2.576843721670156E16 7 2.576843721670156E16 0 2.576843721670156E16 1 2.576843721670156E16 5 2.576843721670156E16 6 2.576843721670156E16 0, как вы, можете считать.Был бы рад отправить больше кода, если это необходимо, если есть другая проблема с частью кода.Я чувствую, что это как-то связано с тем, что оператор по модулю фанк с двойниками.Спасибо за любую помощь!

1 Ответ

0 голосов
/ 01 декабря 2018

Ваш подход не будет работать с double, так как из-за накопленной ошибки округления у вас останется несколько цифр.Чтобы преобразовать двойное число без потери точности, вы должны использовать исключительно целочисленную арифметику.т.е. используйте Double.doubleToRawLongBits(d) и работайте оттуда в формате IEEE-754.

Вот пример, который я написал ранее.https://github.com/OpenHFT/Chronicle-Bytes/blob/master/src/main/java/net/openhft/chronicle/bytes/BytesInternal.java#L1513

Но когда я ввожу длинный номер, такой как 25768437216701562, я получаю: 2.576843721670156E16

Это потому, что 2.576843721670156E16 является ближайшим представимым значениемследующее значение после этого - 2.5768437216701564E16

. Это можно увидеть с помощью следующего, который принимает 64-разрядное плавающее значение, как если бы оно было 64-разрядным.

System.out.println(Double.doubleToRawLongBits(25768437216701560.0));
System.out.println(Double.doubleToRawLongBits(25768437216701564.0));

печатает

4852315308354829086
4852315308354829087

Так же, как нет длинного представления между этими двумя длинными значениями, также не существует двойного представления между ними.

...