#java
#java
Вопрос:
Обе эти функции преобразуют Long в двоичную строку, но является ли одна более оптимизированной, чем другая? Я просмотрел исходный код для класса Long, и эти два статических метода имеют разные реализации.
Комментарии:
1. Я был бы шокирован, если
toBinaryString
бы не был оптимизирован для этой задачи.2. toString использует операции остатка и деления для построения цифр, но toBinaryString использует сдвиги вправо. Но я не уверен, оптимизирует ли компилятор деление на и и остаток от 2, используя сдвиги. Так что я не могу сказать, будет ли какая-то существенная разница. Если оптимизация компилятора выполнена, я ожидаю, что они будут очень похожи. Просто мои мысли, не уверен, правда это или нет.
3. Из быстрого теста (все еще не с анализом JMH / JIT, но придерживаясь некоторых методов микробеншмарк) кажется, что «основной» цикл преобразования (который записывает цифры в
char
буфер) может быть только на ~ 25% медленнее для универсальногоtoString
метода. Но значительные дополнительные накладные расходы могут быть связаны с тем фактом, что вtoString
методе соответствующая частьchar
массива должна быть скопирована при создании строки. ВtoBinaryString
, количество требуемых символов вычисляется напрямую , и результирующийchar
массив передается в строку без его копирования.
Ответ №1:
Ответ легко получить, просто проведите тест:
class Test {
public static void main (String args[]) {
long millisStart = System.currentTimeMillis();
for(int i = 0; i < 1000000; i ) {
String s = Long.toBinaryString(i / 10000);
}
System.out.println(System.currentTimeMillis() - millisStart);
millisStart = System.currentTimeMillis();
for(int i = 0; i < 1000000; i ) {
String st = Long.toString(i / 10000, 2);
}
System.out.println(System.currentTimeMillis() - millisStart);
}
}
В системе, на которой я тестировал это (Raspberry Pi), это приводит к 655 против 3279.
Итак, я бы предположил, что Long.toString(num, 2); медленнее. Что неудивительно, поскольку она должна быть гибкой.
Комментарии:
1. (Я не сторонник отрицательного мнения, но) хотя надлежащий бенчмарк, скорее всего, пришел бы к аналогичному выводу, бенчмарк в данной форме никоим образом НЕ является надежным.
2. Не должен был быть надлежащим эталоном. Однако, когда дело доходит до величин различий в сочетании со специализацией для определенных функций, он по-прежнему дает четкий ответ на вопрос «является ли один более оптимизированным, чем другой?».
3. Спасибо за тест, Флориан. Я больше смотрю, может ли кто-нибудь заглянуть в исходный код и объяснить, ПОЧЕМУ toBinaryString более оптимизирован, предполагая, что это так. (Кстати, я не сторонник downvoter)
4. @user2603017 Не беспокойтесь, помогает прояснить суть вопроса. Как намекнул Армин Дж, оптимизаторы могут оказать здесь немалое влияние. Компиляторы Jit, как правило, ведут себя по-разному в зависимости от платформы.
Ответ №2:
Основное отличие заключается в том, как отображаются отрицательные числа.
var s = System.out;
Long oL = 0L;
long num = -1;
s.println(oL.toString(num, 2) ); //binary result
s.println(oL.toBinaryString(num) );
s.println("0x" oL.toHexString(num).toUpperCase() );
Вывод:
-1
1111111111111111111111111111111111111111111111111111111111111111
0xFFFFFFFFFFFFFFFF
toString() использует математическую нотацию.
toBinaryString() учитывает способ, которым отрицательные числа фактически реализованы в аппаратном обеспечении.