четверг, 23 декабря 2010 г.

Подводные камни дробных чисел

В PHP такой код выдаёт странный, на первый взгляд, результат:
$x = (0.1+0.7)*10;
echo $x, "\n";
printf("%d\n", $x);
echo (int)$x, "\n";
printf("%0.10f\n", $x);
Казалось бы, должна быть всегда восьмёрка. Но этот код выдаст:
8
7
7
8.0000000000
Всё становится ясно, если в код добавить такую строку:
printf("%0.20f\n", $x);
Получим число 7.99999999999999911182
Т.е. в памяти была далеко не восьмёрка, а приведение типа просто отбрасывает дробную часть. Если округлить результат, то точность повысится:
$x = round((0.1+0.7)*10);
echo $x, "\n";
printf("%d\n", $x);
echo $x, "\n";
printf("%0.10f\n", $x);
printf("%0.20f\n", $x);
Выдаст:
8
8
8
8.0000000000
8.00000000000000000000
Поэтому стоит избегать использовать числа с плавающей точкой там, где требуется целочисленный результат.

Twitter

Завёл аккаунт на Twitter: http://twitter.com/Ktak_007

понедельник, 6 декабря 2010 г.

StarDict -> GoldenDict

Сегодня заменил  некогда любимый StarDict на GoldenDict.

StarDict давно уже подглючивал - падал при выделении слова в режиме сканирования, не воспроизводил озвучивание слова.

Вычитал на LOR о другом словарике - GoldenDict - и решил его попробовать. Благо, в Debian этот пакет ставится лёгким движением руки: apt-get install goldendict

Приятно, что мне не пришлось ничего настраивать - новый словарик подхватил все настройки словарей от StarDict и хорошо с ними работает:


Сканирование есть, звук есть. Всё зашибись. Один недостаток - я в Гноме, а GoldenDict на Qt. Но на фоне поедания памяти фаерфоксом мне ничего не страшно :-)

P.S. 20 декабря обнаружил, что StarDict нормально сканирует и звук выдаёт. Наверное, какое-то обновление помогло. Но, всё равно, GoldenDict красивее.

четверг, 2 декабря 2010 г.

Паковать музыку в формате flac и CD "Два в одном"

Уже, наверное, несколько лет ничего сам не паковал. А тут вдруг решил паковать имеющиеся CD в формат flac - для удобства, чтобы всё было
под рукой.

При вставке CD мой Debian Squeeze автоиматически запускает программу Sound Juicer 2.28.2, которая, вроде бы, умеет паковать в формат flac. Попытка упаковать им оказалась неудачной - в файлах с расширением .flac оказалось нечто непрослушиваемое в формате, похожем на mp3.

Вспомнил, что когда-то грабил и паковал в формат mp3 программкой Grip. Поставил (apt-get install grip из-под рута) и запустил. Кажется, она совсем не изменилась, хотя я помню её со времён GTK1:


Видим, что Grip автоматически по базе freedb.freedb.org определил название диска, исполнителя и названия треков.

Чтобы начать паковать, необходимо:
  1. До запуска grip установить пакет flac: apt-get install flac из-под рута
  2. Выбрать требуемые треки. Чтобы выбрать все треки, надо кликнуть по слову "Извлечение" на скриншоте
  3. В разделе Конфигурация/Сжатие проверить, что выбрана программа сжатия flac
  4. Для корректного задания полей flac, командую строку рекомендую сделать такой: -V -8 -T "TITLE=%n" -T "ARTIST=%a" -T "ALBUM=%d" -T "DATE=%y" -T "TRACKNUMBER=%t" -T "GENRE=%G" -o %m %w (почему-то grip сам не умеет правильно подставлять поля во flac, хотя в mp3 теги расставляет корректно)
  5. Формат сжатого файла сделал таким: ~/music/%A/%d/%t. %n.%x (понять подставляемые значения %A, %d, %t и других можно в справке, в самом низу текста: Помощь/Конфигурирование Grip)
  6. Теперь переходим на вкладку Извлечение и нажимаем кнопку "Извлечь и сжать". Вуа-ля! Grip начинает читать диск и параллельно паковать.
Однако это не всё. Если бы диск содержал один альбом, я бы успокоился. Но на скриншоте можно видеть, что  я вставил в CDROM диск, на который записаны два альбома - "Paranoid" и "Technical Ecstasy". Grip создаёт структуру файлов по описанию. В итоге в каталоге ~/music/ у меня появился каталог "Black Sabbath" (это исполнитель), а в нём один каталог-название альбома "ParanoidTechnical Ecstasy" (слеш пропал из названия, т.к. grip по дефолту вырезает неудобные символы). А мне хотелось бы хранить эти альбомы по отдельности - так, как их выпустили в оригинале. Что бы провернуть сие, я воспользовался утилитой metaflac, входящей в уже установленный пакет flac.

Сначала я разделил каталог "ParanoidTechnical Ecstasy" на два: "Paranoid" и "Technical Ecstasy". В первый я переместил песни с 1-ой по 8-ую, во второй - все остальные.

Какие проблемы остались? Это неправильные теги. Просмотреть теги flac-файла можно командой metaflac --list <файл.flac>.

В альбоме Paranoid необходимо исправить только название альбома: 
metaflac --remove-tag=ALBUM *
metaflac --set-tag='ALBUM=Paranoid' *
Удаление необходимо т.к. --set-tag не заменяет тег, а добавляет второй.
С первым альбомом полностью разобрался.

В альбоме "Technical Ecstasy" так же просто, исправляем название альбома: 
metaflac --remove-tag=ALBUM *
metaflac --set-tag='ALBUM=Technical Ecstasy' *

И год выхода альбома (здесь проставился год выхода Paranoid - 1970):
metaflac --remove-tag=DATE *
metaflac --set-tag='DATE=1976' *

По аналогии так можно менять любые теги.

Теперь начинается самое интересное! В этом альбоме у меня файлы имеют вид:
09. Back Street Kids.flac
10. You Wont Change Me.flac
11. Its Alright.flac
12. Gypsy.flac
13. All Moving Parts Stand Still.flac
14. RocknRoll Doctor.flac
15. Shes Gone.flac
16. Dirty Women.flac

Надо заменить номера файлов. Выполняем с командной строки:
i=1; for f1 in *; do f2=`echo $f1 | sed 's/^[0-9][0-9]//'`; printf "mv '$f1' '%02d$f2'\n" $i; i=$((i+1)); done | sh

То же самое с номерами треков - они начинаются с девятки, а должны с единицы:
metaflac --remove-tag=TRACKNUMBER *
i=1; for f1 in *; do printf "metaflac --set-tag='TRACKNUMBER=%02d' '$f1'\n" $i; i=$((i+1)); done | sh

Вуа-ля! У меня два альбома из одного диска с правильными тегами!

Думаю, не упростить ли теперь процесс разбивки альбома на части - написать какую-нибудь GUI-прожку с кнопками. Или патч к Grip написать?