Multiplying word variable overflow problem

Flitch

New Member
Hi guys, I am doing a little project for college and I have two word variables to multiply, and need to get another word as result (calculating P = U * I). My voltage maximum is 12 228 (mV) and current maximum is 1100 (mA) so power maximum should be 13 450 800 with last 3 digits ignored (divided by 1000) 13 450 mW which should be in bounds for word size variable.

This is my code but it seems to have ~50 mW error

let Power = Current / 10 ;Dividing current with 10
let GeneralPurp = Voltage /100 ;Dividing voltage with 100, total division 1000 = ignoring last 3 digits of power
let Power = Power * GeneralPurp ;Multiplying it

I have tried various combinations with * and ** but i have no idea how to merge those 2 words into 1

Anyone got idea how to solve this?

As you can see in this picture, (4.437 * 0.078 should be 0. 346 not 0.308) which is almost 40 mW error
13181004_10206241326618961_1552125363_n.jpg
 

AllyCat

Senior Member
Hi,

We may need to see your actual program code, but if you're dividing 78 (mA) by 10 to produce 7 (integer result) , then there is your approximately -10% error.

Together, the * and ** operators can produce a 32-bit result (> 1 billion) so there is no need to divide the input values down and lose accuracy. Then, there are various ways to scale down the 32 bit result, several recently in the code snippets section, for example my 31 bit division routine.

Cheers, Alan.
 

Flitch

New Member
What i know is what happens with W1 = U*I and W2 = U**I, just i have no idea how to manipulate W1 and W2 to divide by 1000 (so i get number which is actualy 16bit), and put in 1 word sized variable. I have seen some people add them w1+w1 but that didnt work for me.

example with maximum values:
12 228 * 1100 = 13 450 800 with last 3 digits useles for me
13 450 800 in binary = 0000 0000 1100 1101, 0011 1110 0011 0000 ; calculated result, upper and lower word
13 450 in binary = 0011 0100 1000 1010 ;wanted result

so basicaly my question is how to manipulate W1 and W2 to get what i want?

Here is whole code, but i dont think anyone will find it useful, its around 600 lines of code, documented in croatian (since its for my college), and most of calculations inside are based on hardvare voltage deviders or amplifiers.
https://www.dropbox.com/s/9ljt8pjbv5fvvyd/kod.pdf?dl=0


Edit: Thanks, this 31 bit division routine seems to be complete answer :D
 
Last edited:

marks

Senior Member
Hi Flitch,

It would be interesting to know what the project is...

it does make it easier to write some code when you give the maximum ranges like you've done

here's an example to try after seeing your picture I've rounded up the result (hopefully it'll do what you want).
Code:
SYMBOL I  = W0
SYMBOL V  = W1 
SYMBOL P  = W2 


I=1100    'ma
V=12228   'mv 

P=I*34**63164
P=V*2**P

SERTXD (CR, LF, #P)
 

Flitch

New Member
This routine seems to be much simpler than 31bit division, would you please explain how it works? why 34, why 63164, and why 2 (i assume that is bitshift)
 

hippy

Ex-Staff (retired)
This routine seems to be much simpler than 31bit division, would you please explain how it works? why 34, why 63164, and why 2 (i assume that is bitshift)
I cannot answer as to why the values are as they are, but it would seem that what marks is proposing is not to divide by 1000 but multiply by a number and then divide by 65536.

V*I/1000 = V*I*K1/65536

1/1000 = K1/65536, K1 = 65536/1000 = 65.536

That presumably gives overflow with maximum I, so halve K1, and multiply by 2 in the second step.

t = I * 32.768
P = V * t * 2 / 65536

Then t=I*32.768 is turned into t=I*K2/65536.

My brain's not awake enough to figure out how that becomes *34**63164
 

BESQUEUT

Senior Member
Code:
SYMBOL I  = W0
SYMBOL V  = W1 
SYMBOL P  = W2 


I=1100    'ma
V=12228   'mv 

P=I*34**63164
P=V*2**P

SERTXD (CR, LF, #P)
With some reordering :
P=I*V * 34 * 63164 *2 / 65536 /65536 ' 2 times because there are two **
P=I*V *4 295 152 / 4 294 967 296
This is close to
P=I*V

I do not understand why 63164 is used ; I think 63162 will give a closest result, but maybe there is some good reason tu use 63164
(63162*34*2=4 295 016)
Edit : tried it : the explanation is probably some rounding consideration...

34 is chosen to make I as big as possible, (but less than 65536)
2 is chosen to make V as big as possible, (but less than 65536)
There are many others possibilities. For example :
Code:
[color=Purple]P[/color][color=DarkCyan]=[/color][color=Purple]I[/color][color=DarkCyan]*[/color][color=Navy]59[/color][color=DarkCyan]**[/color][color=Navy]14561[/color]
[color=Purple]P[/color][color=DarkCyan]=[/color][color=Purple]V[/color][color=DarkCyan]*[/color][color=Navy]5[/color][color=DarkCyan]**[/color][color=Purple]P[/color]

[color=Blue]SERTXD (CR[/color][color=Black], [/color][color=Blue]LF[/color][color=Black], #[/color][color=Purple]P[/color][color=Black],[/color][color=Red]" 134508"[/color][color=Blue])[/color]
But Marks code give you the bigest possibilities for I and V...
I can be as big as 1927
V can be as big as 32767

Note that I is known with only 10 significants bits.
So P cannot be known with more than 10 significants bits, IE the better possible result is 1345

If I can be read as 1100.0, (14 bits) then 13451 would be an acceptable result.
 
Last edited:

hippy

Ex-Staff (retired)
t = I * 32.768

t = I * 34 * K2 / 65536

32.768 = 34 * K2 / 65536

K2 = 65536 * 32.768 / 34 = 63161

So I make it -

P = I * 34 ** 63161
P = V * 2 ** P
 

Flitch

New Member
I have used marks code and it work flawless, maximum error is +/- 1 mW which is huge improvement (my initial error was 50 mW, and my best scenario was 9 mW error)

Thanks to everyone for help :D

here's a picture with marks equation
13181004_10206241326618961_1552125363_n.jpg
 
Top