2進数の浮動小数点が原因
JavaScriptのNumberはIEEE 754の倍精度(64bit)です。0.1は2進数にすると割り切れない循環小数になるため、0.1+0.2は0.30000000000000004になります。これはJavaScript固有の不具合ではなく、同じ方式を使う多くの言語で起こります。
丸めるのは表示するときだけ
計算の途中で丸めると、誤差が積み重なります。計算は丸めずに行い、画面に出す直前にtoFixedやIntl.NumberFormatで丸めるのが基本です。toFixedは数値ではなく文字列を返す点にも注意してください。
金額は整数で扱う
円や銭など最小の単位に直して整数で計算し、最後に戻す方法が安全です。整数で正確に扱えるのはNumber.MAX_SAFE_INTEGER(2の53乗−1)までで、それを超える場合はBigIntを使います。