Path: csiph.com!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c Subject: Re: How to avoid an overflow during multiplication? Date: Tue, 04 Jan 2022 07:20:02 -0800 Organization: A noiseless patient Spider Lines: 40 Message-ID: <86bl0ry1ct.fsf@linuxsc.com> References: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="2bc79595ad25cbbea7e3c7177d1db1a2"; logging-data="25376"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19gIqX1hoCZX8Xet6fo4fo8xKTRL+0DRyM=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:Rc0tqWOjjOxjMPkjBLSxcp7jy08= sha1:3WEBGKiB2xysWVRQcDRZyclIQbs= Xref: csiph.com comp.lang.c:164270 Mateusz Viste writes: > [ want to compute the value of '(ticks * tempo) / grouplen' ] > > [ that expression ] was working fine on 95%+ of cases > > It broke up when I've got a file with an unusually high tempo value: > 1090909. > > Now, to clarify the context, here's what the values are really: > > "grouplen" is a MIDI time division (16-bit): > https://www.recordingblogs.com/wiki/time-division-of-a-midi-file > > "tempo" is a MIDI tempo value (24-bit, but usually between 300 and > 1000000): > http://midi.teragonaudio.com/tech/midifile/tempo.htm > > "ticks" is a MIDI delta-time (up to 28 bits, but usually between 0 and > 10*tempo): > http://midi.teragonaudio.com/tech/midifile/vari.htm Given this additional information -- in particular, that ticks and tempo have 32 bit types, and grouplen has a 16 bit type -- a more exact calculation suggests itself: #include uint32_t ticks2time( uint32_t ticks, uint32_t tempo, uint16_t grouplen ){ uint32_t a = ticks, b = tempo, c = grouplen; uint32_t aq = a/c, ar = a%c, bq = b/c, br = b%c; return aq*b + ar*bq + ar*br/c; } with the usual comments about precomputing 'bq' and 'br', if that turns out to be important. This approach should give correct values in all cases when the result fits in 32 bits.