All streams
Search
Write a publication
Pull to refresh
51
0.2
Valentin Nechayev @netch80

Программист (backend/сети)

Send message
Десятичная плавучка сама по себе имеет для финансовых целей только одно объективное существенное преимущество: это возможность контроля за корректностью операций через inexact exception. Если в decfloat32 ровно 7 цифр мантиссы, а мы складываем 99999.99+0.02 и получаем 100000.00 (100000.01 округлилось) — нам про это inexact скажет. В двоичном варианте практически любые операции с долями приведут к жуткому зашумлению inexactʼами даже на вполне законных операциях.

А где нет inexactʼа (как .NET Decimal) — нет даже этого преимущества.

Второе преимущество уже не в качестве операций, но в устранении проблем понимания. Когда вопрос «Floating point is broken? 0.1+0.2 != 0.3» задаётся на Stackoverflow каждые пару дней — это показывает реальный барьер: людям сложно понимать двоичную плавучку. И десятичная тут помогает не отпугнуть широкие массы тех, кого нельзя по-честному называть программистами, но без кого на нынешнем безрыбье не обойтись ;( да, я тут чуть снобствую, для ясности объяснения.

Всё остальное у десятичной арифметики хуже. Точность операций хуже, за счёт размера младшего разряда. Реализации сильно сложнее, и аппаратно, и программно.

Если есть возможность делать финансовую арифметику на целых числах (копейки, сотые доли копейки — где как надо) — лучше делать так, несмотря на присутствие десятичной плавучки. (Разумеется, при наличии контроля переполнений. Это другая проблема, местами тяжёлая.)
Десятичная плавучка, считаем, работает только у IBM, но сразу на двух их железных платформах — zSeries (S/390) и Power. Зато у них работает сразу с BCD (Chen-Ho) мантиссой.
Есть поддержка в GCC (почему-то только для C), софтово, с двоичной мантиссой.
> «Сутя по тысячам терминалам и сотням станций разных вендоров которыя я настраивал» таки у вас нетипичные клиенты.

Вот вытащил из архива совершенно типовой INVITE от железяки системы SPA2000 (Sipura, потом Linksys). Её наследники напложены в десятках миллионов штук. Тут участвовал наш B2BUA, но состав полей в SDP сохранён.
Скрытый текст
INVITE sip:000999529@192.168.0.77:5060 SIP/2.0
Record-Route: <sip:10.0.87.41;ftag=e9345eee27d4d78154172d5c75a97e80;lr>
Via: SIP/2.0/UDP 10.0.87.41;branch=z9hG4bKa868.5d6d0a34bfee705e16121b68c7228f10.0
Via: SIP/2.0/UDP 10.0.87.41:5061;branch=z9hG4bKa0a9c8877cfaf254628c2413433968f3;rport=5061
Max-Forwards: 16
From: 000999528 <sip:000999528@10.0.87.41>;tag=e9345eee27d4d78154172d5c75a97e80
To: <sip:000999529@10.0.87.41>
Call-ID: d591387e-aaf46616@192.168.0.60
CSeq: 200 INVITE
Contact: Anonymous <sip:10.0.87.41:5061>
Expires: 300
User-Agent: Sippy
Content-disposition: session
Content-Length: 464
Content-Type: application/sdp

v=0
o=Sippy 137702988 0 IN IP4 10.0.87.41
s=-
t=0 0
m=audio 35000 RTP/AVP 0 2 4 8 18 96 97 98 100 101
c=IN IP4 10.0.87.40
a=rtpmap:0 PCMU/8000
a=rtpmap:2 G726-32/8000
a=rtpmap:4 G723/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:18 G729a/8000
a=rtpmap:96 G726-40/8000
a=rtpmap:97 G726-24/8000
a=rtpmap:98 G726-16/8000
a=rtpmap:100 NSE/8000
a=fmtp:100 192-193
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
a=ptime:30
a=sendrecv
a=direction:active



Это уже 1105 байт. Пара хопов больше — ещё по ~90 байт на каждый — уже к границе 1300 подобрались вплотную.

И это, заметьте, без отдельных бесплатных кодеков — как раз на ITU.T наборе (G.711/723/726/729). С ними переход произошёл бы ещё быстрее.

Если Вы считаете, что такие клиенты нетипичны — скажите, какие, по-Вашему, типичны.

> Проблемы кривой настройки. Пихать десяток кодеков из соображений — «может что подойдёт», это лишь показатель кривизны рук.

Ну я тоже могу обвинить Cisco (в лице Linksys) в кривых руках, но меня вряд ли поймут ;)
> выигрываем в производительности и без того ресурсоёмкой задачи.

Выигрыша нет, QtWQ безусловно и одинаково вычисляется в обеих ветках. Если написано Qtw*Qtw.', это оно же.
Или Вы предполагаете, что в else реально происходят «ленивые вычисления» и работа с QtWQ «размазывается» на остальном? Такое я про матлаб пока не слышал, хотя готов поверить, если подтвердят.
QtWQ в обеих ветках вычисляется одинаково. Поэтому лучше его вынести в безусловное вычисление за пределы развилки.
После того, как это сделано, оказывается, что оба вычисления для u имеют одинаковую форму:

u=((6*(1-p)*QtWQ+p*R)\diff(divdif)


и «else» вообще не нужна, а «then» просто меняет значение p; вычисление u может быть сделано общим кодом после завершения развилки.

Мне лично кажется, что после этих изменений код будет понятнее и сопровождабельнее.
Если нужен не-vi-like редактор, всегда сношу nano и ставлю joe. В отличие от nano, у него управление в разы понятнее, и достаточно удобно.
Но в реальности привык использовать vim для всего, где не нужно IDE с полным набором уже специфичных плюшек вроде рефакторинга.
«Системный монитор» в микрокомпьютерах того времени это аналог BIOS в линии x86. Входят некоторые стандартные процедуры типа вывести символ на экран в режиме телетайпа, настроить видеорежим и т.п., стартовая инициализация и помощь в загрузке, если умеет грузиться с диска.
Точно так же было на Apple II и его советском клоне «Агат».
Так что поиск должен завершиться результатом в виде списка этих системных подпрограмм (адреса вызова, интерпретация регистров).
Так таких «достаточно умных» днём с огнём не напасёшься.
Нет, так как раз не получится. Раутер послал свой needfrag и забыл. Он не будет ставить у себя память «вот для этих спецправило — ставить MSS». Такое спасение утопающих — только их дело, в лучшем случае, ближайшего своего шлюза.
> Ну то есть вы согласны — что такая ситуация в реальной жизни маловероятна?

Не-а. Может, это специфика клиентов моей прошлой работы, но такого было валом. Ну пусть не 15 кодеков, но по 10 пытались выставлять, и параметры вписывались чуть менее, чем все. Я мерял — INVITE толще граничных 1300 байт были регулярно.

> В нормально настроенном оборудовании IMHO, нужно всего 3 кодека

Судя по тому, что в типичной железяке, с которой мы работали, были G.711, G.723 в двух профилях, G.729 в двух профилях, GSM, Speex — с Вами мало кто согласен :) Обычно предпочитают выставить побольше, лишь бы связаться хоть как-то. Очень не любят ситуацию, когда звонок не устанавливается потому, что не нашли общего кодека.
А так как до сих пор есть два слабопересекающихся мира с проприетарными и со свободными кодеками, где на пересечении только G.711, который зарезан потому, что слишком большая полоса (а некоторые клиенты из крупных азиатских стран реализовывали свой менталитет зарезанием всего, что толще ~8Kbit/s) — то такое несогласование происходило постоянно. Если удавалось уговорить обе стороны в таком варианте на GSM — это уже была маленькая победа.
> с редактированием заголовка TCP.

Если имеется в виду добавление опции TCP MSS, то если во встречный пакет такое добавили — хорошо, но если не добавили? Как это «умное промежуточное устройство» узнает про необходимость добавлять MSS для конкретного маршрута? Обычно эту опцию вынуждены включать глобально, чтобы хоть как-то работало, и соответственно понижая эффективность всех передач.
> По умолчанию везде SIP использует UDP транспорт.

Цитирую RFC3261:

>> If a request is within 200 bytes of the path MTU, or if it is larger than 1300 bytes and the path MTU is unknown, the request MUST be sent using an RFC 2914 [43] congestion controlled transport protocol, such as TCP.

Тут даже не SHOULD, тут MUST. Которое, конечно, игнорируют «не только лишь все», но многие на него смотрят и ожидают соответствующего.
> При работе с VoIP (статья то VoIP? правильно? прямо так в первом предложении и написано) вы врядли встретитесь с проблемами фрагментации.

Запросто — когда SDP в INVITE перечисляет пятнадцать кодеков с подробным перечислением свойств каждого, в Via уже несколько записей транзита, а From, To увешаны атрибутами как новогодняя ёлка.
> Во-вторых, после обновления то же библиотеки надо рестартить использующий её софт, потому что в запущенных процессах всё ещё используется старая версия.

Так если используется старая — это ещё хорошо :) Хуже, если файл меняется на ходу, а он используется как библиотека. Для основных бинарников это блокируется ядром, для библиотек — не везде. В результате получаем, например, такое (Firefox с обновлённой freetype):

image

Тут уже зависит от поведения менеджера пакетов.

А необходимость рестарта хорошо отображает, например, zypper (из OpenSuSE). «zypper ps» показывает, кого надо перезапустить по мере возможности.
Аналога для apt что-то не видно (из коробки).
> мы теперь не можем заказать интервал более половины максимально возможного числа, вернее, заказать можем, но он прекратится мгновенно, так что Вам решать, стоит ли выигрыш подобного ограничения. В Linux системах принят именно последний вариант

Ну это по крайней мере логично. Легче поднять этот интервал, чем бороться с эффектами на краю переполнения.

> А надо использовать MISRA и вообще не напрягаться

А можете сформулировать, что тут говорит MISRA?
Запрет break, continue, и return не последним оператором — это норма для «самого строгого» варианта принципов структурного программирования. Не слышал автора по этому поводу, но вообще такие нормы есть.

На практике это превращается в создание пачки дополнительных булевских или целых флагов, которые контролируют продолжение цикла или вход в отдельные ветки исполнения. Такое преобразование может быть сделано и вручную, и автоматизированно анализатором.
Движок должен допускать хвостовую рекурсию. Если для него это не гарантируется, использовать подобные приёмы нежелательно.
> С другой стороны решение простейших вопросов превращается в вязкое болотце. Это модель удобна для стабильно работающего бизнеса, где все отлажено. Но какието новые свершения даются с колоссальным трудом. Имея в штате дизайнера за день-два можно получить готовую листовку, с фрилансером на это уходит месяц-полтора изматывающих согласований, не говоря о каталоге.

Это специфика или конкретных задач, или людей. Или просто лень.

На двух из моих работ повторилось одно и то же: когда мы по разным причинам сидели на нескольких разбросанных по городу точках, общаясь в основном в рассылках или через тикетницы, работа шла очень хорошо и быстро — при том, что это был типичный период полуначального построения, когда уже понятно, куда идти, но ничего не отлажено, и каждый день что-то меняется на ходу. Когда же всех свели в один офис — люди буквально за год отучились нормально решать вопросы удалённо.

И для дизайнера не вижу причины, почему нельзя всё показать удалённо. Разве что нужно трёхмерную модель крутить с нужным темпом в нужную сторону :) но это редко.

Судя по Вашему рассказу, удалёнка у Вас таки работает. Тогда, значит, не настолько «вязкое болотце»?
> синтаксис значения по умолчанию для аргумента функции off: Int = 0 явно разрабатывался в Мюнхенском офисе (как по-немецки говорят «сто четые и двадцать», а не «сто двадцать четыре»).

Это спорно. Да, есть традиция (которую сохраняет C и потомки), что формат определения переменной — «тип переменная [=начальное]», в противоположность традиции, известной по Pascal и прочим — «var переменная: тип [=начальное]». Но сишная традиция заметно усложняет парсинг (уже лексер должен отдавать, чем является идентификатор — типом, переменной, чем-то иным; или парсер должен справляться с неоднозначностями уже после построения конструкций), формат записи (все эти foo (*fptr)(bar) долго учатся новичками)…
Для сравнения, Go использует паскалевский вариант (только ':' убрали — «var переменная тип») — в нём много спорных моментов, но этот явно выглядит как результат идеи прекратить топтаться заново по этим граблям. Swift использует паскалевский вариант. По сравнению же с вот такими чудесами — неудивительно, что пытаются упрощать.

Это же касается и второго замечания:

> аналогично fun — лишний визуальный мусор

та же тема — упрощение грамматики приводит к понятности всем. Дополнительно, такой fun позволяет сделать простой и ясный синтаксис замыканий/лямбд (что показал хотя бы Javascript).

> по умолчанию класс не наследуется (так взяли и задушили всю прелесть OOП)

Это показывает определённый настрой, но не выглядит фатальным — ведь всегда можно умолчание изменить? В C++ умолчание для метода — не виртуальный, в Java/C# — виртуальный, от этого в C++ стало меньше возможности перекрыть метод?

> ключевое слово override для метода — лишний мусор по сравнению с Override.

Ну, тут лучше было бы поступить радикально — как по требованию .NET CLR — метод сделать любой идентификатор, даже совпадающий с ключевым словом. Если это есть — несколько лишних ключевых слов не проблема.
Тут интереснее. Это для нас r и l различаются. Для китайцев, японцев, представителей многих других соседних народов — нет. Даже обучившись европейским языкам, они сохраняют эти проблемы ещё долго.
Соответственно, использование языка будет давать им серьёзные проблемы там, где надо озвучивать код — при обучении, в рабочих дискуссиях… А так как тех же китайцев в США несть числа — ожидаю активное неприятие языка.

Information

Rating
2,713-th
Location
Киев, Киевская обл., Украина
Date of birth
Registered
Activity