Стендап Сьогодні 📢 Канал в 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, безумовно.)