Just in case the below wasn't explicit enough, the info below would be converted into C as follows: result =3D input / 125; // Original result =3D input / 128 + input / 8192 + input / 16384 + input / 262144; // To binary equivalant ( with 0.007% error) result =3D input >> 7 + input >> 13 + input >> 14 + input >> 18; // Using shifts rather than division (faster, same result) Slightly faster (since a one bit shift takes a full instruction cycle): temp =3D input; temp =3D temp >> 7; result +=3D temp; temp =3D temp >> 6; // temp =3D input >> 13 result +=3D temp; temp =3D temp >> 1; // temp =3D input >> 14 result +=3D temp; temp =3D temp >> 4; // temp =3D input >> 18 result +=3D temp; This can be optimized further, but it only requires a total of 18 shifts (whereas the previous version might have actually generated 52 shifts) and a similar number of additions. Across a 48 bit number on an 8 bit processor this adds up... If you decide you only need 1% accuracy, then you only need the first two factors (128, 8192), and if you want 0.001% accuracy you need 6 factors (128, 8192, 16384, 262144, 2097152, 8388608). -Adam On Wed, Apr 29, 2009 at 10:38 AM, M. Adam Davis wrote: > This should give you what you need - you can turn a division into a > sum of several binary divisions: > > http://piclist.com/techref/method/math/divconst.htm > > There is an online code generator here, though it only goes up to 32 > bits, but you probably don't care about the code generated, just the > binary division factors: > http://www.piclist.com/techref/piclist/codegen/constdivmul.htm > > 1/125 =3D 0.008, which happens to be very close to: > > ; ALGORITHM: > ; Clear accumulator > ; Add input / 128 to accumulator > ; Add input / 8192 to accumulator > ; Add input / 16384 to accumulator > ; Add input / 262144 to accumulator > ; Move accumulator to result > ; > ; Approximated constant: 0.00799942, Error: 0.00724792 % > > http://www.piclist.com/cgi-bin/constdivmul.exe?Acc=3DACC&Bits=3D32&endian= =3Dlittle&Const=3D.008&ConstErr=3D0.05&Temp=3DTEMP&cpu=3Dpic16 > > You can change the "ConstErr=3D0.05" to a finer value to reduce the error= further. > > -Adam > > On Wed, Apr 29, 2009 at 3:14 AM, William "Chops" Westfield > wrote: >> I want to calculate: >> >> =A0 =A0(ticks * ) / 1000 >> >> to return the number of milliseconds elapsed based on a count >> maintained by a timer ISR. =A0microsecondsPerTick is a nice constant >> number like 1024 or 2048, so the multiplication becomes a shift, and >> factoring out twos I get: >> >> =A0 =A0(ticks * (microsecondsPerTick/8)) / 125 >> >> "ticks" is at least 40 bits, however, and the multiplication MUST NOT >> OVERFLOW (been there, trying to fix that!), so I'm looking at at at >> least a 48bit intermediate value. >> >> It would be nice if the code were in C. =A0Avr gcc, in particular. >> There are 8, 16, 32, and even 64 bit math functions available, but of >> course they're *C*, so they don't let you actually do mixed-sized >> math, nor are they likely to optimized >> >> The code is not particularly time critical, but it would be nice if it >> were as small and fast as possible (using 64bit long longs seems >> excessive.) >> >> Thoughts? =A0Any pointers to mixed-size C math functions in general? =A0= In >> principle, I think I understand how to do this, but ... =A0Is there a >> way to take advantage of the constant? =A0Of 125 in particular? =A0(lots >> of one bits there...) >> >> Thanks >> Bill W >> >> -- >> http://www.piclist.com PIC/SX FAQ & list archive >> View/change your membership options at >> http://mailman.mit.edu/mailman/listinfo/piclist >> > -- = http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist