Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni
🤖🚫 AI-free content. This post is 100% written by a human, as is everything on my blog. Enjoy!16.06.2023
Чому у Twitter рядкові ID
Хоча ID твітів чисельні, але у їх API вони повертаються як рядки. Чому? На перетині 64-бітних ID та чисел з рухомою комою знаходиться, мабуть, найбільший Wat Джаваскрипта. А саме, те, що великі значення цілих чисел будуть округлені без жодних повідомлень та попереджень.
Причина в тому, що в Javascript є тільки один тип “число”, та це число зберігається як тип double
. Оскільки тип double
теж займає 64 біти, то цілочисельне значення в 64 біти в нього технічно неможливо вмістити.
З цим майже неможливо стикнутись при обчисленнях, бо ніде не потрібні такі великі числа з такою великою точністю. Але схеми генерації унікальних ID, про які я писав, за визначенням мають заповнювати всі 64 біти. Тому з ID округлення практично гарантоване, а наслідки округлених ID будуть від неприємних до катастрофічних.
Насправді така проблема є не тільки в JavaScript, але й в будь-якому середовищі, де числа представлені у вигляді з рухомою комою. Власне, ми знайшли цей нюанс в пропрієтарній мові однієї з наших залежностей. Причому там ще дивніше було, бо числа нібито працювали правильно, доки їх не друкуєш або не конвертуєш в JSON. доки не розумію, як це взагалі може бути. Хіба що число насправді зберігається як int64
.
Не всі мови себе так поводять; наприклад, Ruby в залежності від значення вживатиме цілі числа або рухому кому. А якщо число не влазить в int64
,ʼ то перейде до довгої арифметики, тобто до представлення числа у вигляді необмеженого рядка з байтів. Довга арифметика вже 5 років є й в JavaScript - це тип BigInt, але його треба залучити явно, та сподіватись, що всі це зроблять, не можна. Ну, а з системними мовами проблем точно не буде.
Щоб такого з вами не трапилось, 64-бітні ID треба передавати у вигляді рядка. Якщо почитати документацію API Twitter, то вони саме так і пояснюють. Я б пішов ще далі та замість числа в десятковій системі зробив більш компактний формат, ну принаймні hex
. Це також сприятиме використанню ID у вигляді рядка, без ризикованої конвертації в число. (Але там, де швидкодія має значення, треба перетворювати назад в int64
, безумовно.)