Page 1 of 1
Multiplying or dividing large numbers
Posted: Wed Jun 15, 2011 1:37 pm
by echase
Please remind me. If I do the calc Byte_Variable = 100 x 200/110 the answer should be 181, or 182 if 5/4 rounded. Does the fact that the intermediate answer of 40,000 is beyond the range of both a byte and an integer variable make it inaccurate or require me to rearrange it to say = 100/110 x 200 to keep the intermediate answer to under 255? But will then the intermediate answer of 0.91 be rounded to 1 and give 200 as the overall answer?
Similarly for integers will Integer_Variable = 1000 x 2000/-1100 work?
In summary do I only need to check that the final answer is under 255 or 32,767 respectively or do I need to worry about all the intermediate calculations getting too big and so overflowing, or too small and getting over rounded?
Re: Multiplying or dividing large numbers
Posted: Wed Jun 15, 2011 1:48 pm
by medelec35
From experience using integers any intermediate or final results of calculations must never exceed 32767.
If it does then results will be wrong. The simulator does not take this fact into account.
Re: Multiplying or dividing large numbers
Posted: Wed Jun 15, 2011 2:26 pm
by echase
Also is there a simple Flowcode or C function that returns the absolute value of an integer? I.e. it ignores the minus sign?
Re: Multiplying or dividing large numbers
Posted: Wed Jun 15, 2011 3:25 pm
by Benj
Hello,
It depends what you want to do with the variable.
Flowcode can currently only deal with signed int variables so you could type cast the variable to unsigned but then say you wanted to print out the number on the LCD, the code to allow this assumes a signed variable.
Therefore to do this you would have to use the code customization to modify the print routine to assume an unsigned rather then a signed variable type.
Re: Multiplying or dividing large numbers
Posted: Thu Jun 16, 2011 12:15 am
by echase
I don’t need to put it on an LCD, at least not until lot of post-processing has been done on it so hopefully it will have forgotten that the Absolute function was used. Does this limitation only apply to the Flowcode simulator rather than in the real hardware?
So is the Absolute value created by the MOD function mentioned in the help file and how do I use it for PICs?
Volts = 11 MOD – 24 appears to work as syntax but what is it trying to do? I was hoping for a function like Excel’s
Volts = ABS (Input)
to return the value of the Input integer without the sign.
Else what is the C code to do it?
Re: Multiplying or dividing large numbers
Posted: Thu Jun 16, 2011 6:11 am
by medelec35
Attached is how I would convert signed numbers into unsigned numbers.
Its very simple and does not use C
Since it uses int, it will only convert numbers down to -32768
There maybe a simple method using C e.g using unsigned short, but that's not my area of expertise.
Hope this is what your after
Martin
Re: Multiplying or dividing large numbers
Posted: Thu Jun 16, 2011 9:47 am
by JonnyW
Hi there. In Flowcode v5 we have plans to support unsigned 16 and 32 bit values. It would also be nice to have abs() and sgn() functions and I'll put this on the suggestion list.
Until then, the single line:
result = value * (1 | -(value < 0))
Will do the job of abs() in a single calculation line. It will work whether the value is signed or not.
Cheers,
Jonny
Re: Multiplying or dividing large numbers
Posted: Thu Jun 16, 2011 10:22 am
by echase
Not able to read a FCF file at moment but is medelec’s code basically a Flowcode IF statement:-
IF value< 0, THEN value = - value
Whereas result = value * (1 | -(value < 0)) is presumably C code.
Which is faster on integer variables as in this case these are done within an interrupt and need to be as short as possible?
Re: Multiplying or dividing large numbers
Posted: Thu Jun 16, 2011 10:41 am
by medelec35
echase wrote: but is medelec’s code basically a Flowcode IF statement:-
IF value< 0, THEN value = - value?
Im using If Value < 0 then Value = NOT Value +1
I would guess Jonnys code would be better?
Since it's all on one line
Martin
Re: Multiplying or dividing large numbers
Posted: Thu Jun 16, 2011 11:09 am
by JonnyW
Hi. (NOT value) + 1 is the same as -value, so thats all fine.
You would have to look at the ASM as to which is more efficient. Branches in the code tend to be the main issue on pipelined processors, though I haven't much HW or low level knowledge of the devices you are using. On many platforms, (value < 0) gets generated with a branch anyway, but optimisation of expressions may be slightly more efficient than optimisation of compound statements, such as IF.
Plus, remember that the code I posted has a multiply in it, which may or may not be slow. There are ways without this, but they look more and more ugly.
Personally I think the code I posted isn't as clear as an IF statement, but I have a BBC BASIC background so have always favoured compact lines of code. If we put support for abs() built in to Flowcode, most likely this will be done with a #define and so a single expression would most likely be used.
In short, I would go with which you find most clear and intuitive, as the speed difference shouldn't be that great between the two.
Cheers,
Jonny
Re: Multiplying or dividing large numbers
Posted: Thu Jun 16, 2011 11:11 am
by JonnyW
PS:
'Whereas result = value * (1 | -(value < 0)) is presumably C code.'
This expression will work fine in both C and Flowcode expressions.
Re: Multiplying or dividing large numbers
Posted: Thu Jun 16, 2011 4:25 pm
by echase
Forgive ignorance but can you explain result = value * (1 | -(value < 0)) in words? What is it doing?
| is an OR is it not?
Re: Multiplying or dividing large numbers
Posted: Thu Jun 16, 2011 5:11 pm
by Benj
Hello,
The abs() function that Jonny was talking about does the following.
"Calculates the absolute value (magnitude) of a number. The absolute value of a number is always positive."
http://processing.org/reference/abs_.html
| is indeed a logic level OR operator.
Re: Multiplying or dividing large numbers
Posted: Fri Jun 17, 2011 8:56 am
by JonnyW
Yeah, this is true. In stages:
(value < 0): returns 1 if value -ve, 0 if it is not
-(value < 0): This becomes -1 if -ve, 0 if not
1 | -(value < 0): This unconditionally sets the bottom bit, so is -1 if -ve, 1 if not
If we then multiply this by our original value, we will 'flip' the sign of -ve values.
There are ways to do this without a multiply, but these get even more ugly:
result = (value ^ -(value < 0)) + (value < 0)
Re: Multiplying or dividing large numbers
Posted: Fri Jun 17, 2011 10:51 am
by echase
Benj wrote:Hello,
The abs() function that Jonny was talking about does the following.
"Calculates the absolute value (magnitude) of a number. The absolute value of a number is always positive."
http://processing.org/reference/abs_.html
.
Ben, abs() is what I want but it’s not a Flowcode function for PICs. I tried it. Does it work in C? I think that link is to C code.
The Help file mentions it works for one of the other processor families.
Re: Multiplying or dividing large numbers
Posted: Fri Jun 17, 2011 12:08 pm
by Benj
Hello Echase,
Sorry the abs() function does exist for some Flowcode versions but on the PIC you will have to use Jonny's method as the compiler does not support the function directly.
Edit, I have just looked at the boostC manual and it is saying the abs() function is supported. Can you call it using a C icon?
FCV_VAR1 = abs(FCV_VAR2);
Re: Multiplying or dividing large numbers
Posted: Fri Jun 17, 2011 11:37 pm
by Spanish_dude
I'd probably do something like this : result = (value < 0) ? -value : value;
http://en.wikipedia.org/wiki/%3F:#Condi ... assignment
Cheers
PS: This will need to be written in a C code box instead of the calculation box because I don't think it supports ternary operations.