投稿者コメントエディタで0.01秒ズレる話

/

ニコニコ動画の投稿者コメントエディタを弄っていると、特定の秒数を指定しようとしたときに0.01秒前の秒数になることがあることについての話です。

具体的に何が起こるのか

例えば、コメント時刻を16.06秒とリストで指定しようとすると16.05秒になります。
また、エディタ(json形式)でもtimeを16.06秒と指定してリストに反映すると、16.05秒になります。

原因の推測

コメントの秒数は基本的に小数点以下2桁の秒(0.01秒)が最小単位として管理されているようです。
リストやエディターでは小数点以下何桁でも自由に入力できてしまうので、確定するときに小数点以下2桁の数字に丸めることになります。

適当にソースを読んだところ、(詳細を省くと、)丸め処理は

数字を100倍にして、小数点以下を切り捨て、1/100にする。

というような処理になっています。
(全部がそうかは知りません。)

ところで、JavaScriptの浮動小数点数の計算等には誤差があり、少々増えたり減ったりします。
例えば、以下のように16.06を100倍した数字を見ようとすると、1605.9999999999998と表示されます。

console.log(16.06); // 16.06 console.log(16.06 * 100); // 1605.9999999999998

16.06を100倍すると1605.9999999999998となり、小数点以下を切り捨てると1605となります。
これを1/100倍にすると16.05であり、丸め処理がされる間に16.06が16.05と変化してしまっている、というのが原因のようです。

他の数字で起こる場合も同様に、計算誤差で小さい数字になってしまっているものと思われます。

対策

プログラムで対策されればいいですが、一応手動で対策する方法があります。
16.061秒といった風に、0.001秒だけ後ろを指定してしまえば、少々誤差があっても丸め処理後16.06秒になります。
特に問題なく指定できる秒数、例えば1.00秒でも、1.001秒と0.001秒多めに指定しておいても問題なく1.00秒になるので特に害はないです。
リストで秒数を指定するときでも、エディタ(json)で秒数を指定する時でも、この小技で対処可能です。

欠点は、一度入力を確定したりした後は0.001秒部分が失われることです。毎回0.001秒を付けないと減ります。

例えば、リストで16.061秒を確定した場合、16.06秒となっています。
この状態でエディタ(json)に切り替えると、16.06秒となっています。
この後エディタで16.06の部分をそのまま確定するとリストで16.05になってしまいます。