c++ - How can I preserve the order of multiplications and divisions? -
on 32 bit embedded c++ application, need perform following computation:
calc(int millivolts, int ticks) { return millivolts * 32767 * 65536 / 1000 / ticks; }
now, since int on platform has 32 bits , millivolts has range of [-1000:1000], millivolts * 32767 * 65536
part cause integer overflow. avoid this, have split factor 65536 1024, 32 , and reordered follows:
calc(int millivolts, int ticks) { return millivolts*32767*32/1000*1024/ticks*2; }
this way, long order of multiplications , divisions preserved compiler, function compute correctly.
kerninghan , ritchie state in section 2.12 of "the c programming language" (i don't have copy of c++ standard handy):
c, languages not specify order in operands of operator evaluated.
if understand correctly, compiler free change chosen expression not work intended.
how can write function in such way guaranteed work?
edit: several answers below suggest using floating point calculations avoid issue. not option because code running on cpu not have floating point operations. furthermore calculation in hard realtime part of application, speed penalty of using emulated floating point big.
conclusion: of merdad's answer , matt mcnabb's comment, managed find relevant section in k&r, section a7 says:
the precedence , associativity of operators specified, order of evaluation of expressions is, exceptions, undefined, if subexpressions involve side effects. is, unless definition of operator guarantees ths operands evaluated in particular order, implementation free evaluate operands in order, or interleave evaluation. however, each operator combines values produced operands in way compatible parsing of expressions in appears. this rule revokes previous freedom reorder expressions operators matematically commutative , associative, can fail computationally associative. change affects floating-point computations near limits of accuracy, , situations overflow os possible.
so merdad right: there nothing worry about.
actually:
you (and others) misunderstanding being said. there no problem here.
they're saying if have f(x) + g(y)
, there no guarantee f(x)
evaluated before g(y)
(or vice-versa).
but if have
millivolts * 32767 * 32 / 1000 * 1024 / ticks * 2
it automatically interpreted as
(((((millivolts * 32767) * 32) / 1000) * 1024) / ticks) * 2
which means evaluating left- , right-hand sides of operator out of order not result in problem, since expressions right-hand side of operator either variables or numbers, in either case of evaluation of right-hand side no-op (no side-effects, contrary function call).
thus there nothing worried about.
Comments
Post a Comment