Finding total value of an array of numbers..
def90
Posts: 14
I am programming a security system and I have an integer array for all of the zones in which each array position or zone number will have a value of 0=closed or 1=open. How is the best way to take this data and have a system ready value that is =1 if all of the zones in the array are =0 and system ready value=0 if any position in the array is =1?
0
Comments
Thanks
This sounds like a great application for binary! Use bor and bxor to turn a bit on or off. One integer variable will give you 16 zones. The simply say if (!securityZones) then ready to arm. You could employ many ways to turn on and off the bits. I like using the shift operator. Let me know if you need more detail.
Why not use find_string? No for loop required.
Paul
Any way how would you use the find_string on an integer array?
I don't think I understand what you mean. If you use find_string to search for a 1, the first 1 it comes to will return and you are done.
So if your array looks like this:
array[] = {0,0,0,1,0,0,1,1,1,0,0,0}
then find_string will start looking from the beginning, get to the fourth element and return. It won't continue to look for another 1 since it already found one. I think that is what the OP wanted, where if at least one element is 1, the variable is true or all are 0, the variable is false.
The worst case is this:
array[] = {0,0,0,0,0,0,0,0,0,0,0,1}
where the 1 isn't found until the end, but the same would be true for a for loop search.
A for loop will certainly work, but generally system commands execute more quickly as they have been optimized for the processor.
That is left as an exercise for the reader
Paul
Since I'm a little slower than most of you folks how's about an example.
Execution time is less important to me than just being able to write a line of simple code instead of a for loop for a test. I prefer to write:
rather than:
I really have no idea which would be faster if there is a difference at all. But it just makes for cleaner code, so that's why I prefer to use it.
Paul
That's what thinking feels like
Paul
Well, if you consider that in Netlinx a string is just an array of 8-bit integers (a short integer, I guess), it would seem that if you can search a string for a 0 or 1 that you might be able to do so with an integer array (array of 16 bit integers) as well. I tried it and the expected type error resulted. TYPE_CAST didn't allow it to compile, either. Sometimes you can use an integer in a function that expects a character variable (8 bit/short integer) and get it to work, but not in this case, it seems.
Of course, because the array is being used to store no integer value larger than 255, a CHAR data type can be used instead of an INTEGER type. That should allow the find_string function to work correctly.
For a while a couple years ago I was on a kick to use CHAR variables whenever I wanted a variable that would never exceed 255, but it seems to cause warnings and other annoyances so I abandoned that fetish. Might work just fine in this case, though.
How many zones? This is great stuff for bitwise. Instead of using an integer array use a binary number of 1's and 0's. Use bor to turn on a bit and band to turn it off.
Open Zone1
$00 bor $01 = $01 turning on the LSB of the 8 bit value 00000000 is now 00000001
Close Zone 1
if $01 band $01 $01 bxor $01 = $00 turning off the LSB of the 8 bit value 00000001 is now 00000000
So if all zones are closed then the value for binary value is 0. So if not zones then arm system. Just use a CHAR for 8 Zones or an INTEGER for 16 zones.
Listen to this guy with his binary methods. I have. Good stuff.
What if you have hundreds of zones, like most security systems seem to have these days? Its better to use arrays than bits I would think. Easier to debug, that's for sure, and memory isn't really at a premium like it would be in an embedded device.
Paul
Sure, memory really isn't an issue. However, like Ken, I am always in search or the slickest, least wordy ways of getting things done.
Here is the side by side comparison:
Line 59 (18:04:42.890):: *********************************************************
Line 60 (18:04:42.890):: * TEST 1 REPORT: FIND_STRING 1000x
Line 61 (18:04:42.890):: * Most recent 5 runs:
Line 62 (18:04:42.906):: * 1: 13ms
Line 63 (18:04:42.906):: * 2: 13ms
Line 64 (18:04:42.906):: * 3: 0ms
Line 65 (18:04:42.906):: * 4: 0ms
Line 66 (18:04:42.906):: * 5: 0ms
Line 67 (18:04:42.906):: *
Line 68 (18:04:42.906):: * Average run time: 13ms - over 2 tests
Line 69 (18:04:42.906):: *********************************************************
Line 70 (18:04:42.906):: *********************************************************
Line 71 (18:04:42.906):: * TEST 2 REPORT: FOR Loop 1000x
Line 72 (18:04:42.906):: * Most recent 5 runs:
Line 73 (18:04:42.906):: * 1: 810ms
Line 74 (18:04:42.906):: * 2: 808ms
Line 75 (18:04:42.906):: * 3: 0ms
Line 76 (18:04:42.906):: * 4: 0ms
Line 77 (18:04:42.906):: * 5: 0ms
Line 78 (18:04:42.906):: *
Line 79 (18:04:42.921):: * Average run time: 809ms - over 2 tests
Line 80 (18:04:42.921):: *********************************************************
Here is the code block tested:
A couple of observations:
- I had to switch to a char array as I could not get it to compile using an integer array.
- I had to initialize the char array data to 0 because it was not done automatically.
- I had to set the length of the array accordingly for find_string to work. (I think)
Jeff
Oh and when I said I was slow that was referring to getting find_string to work on an integer array but I guess if you're just tracking 1 & 0 for security zone states it's easy enough to just put them in a char array as chars in what ever size string you need to cover your zones.
bFaultState = 0
length = max_length_array(nArrayTest)
for(x=1000;x;x--)
{
for (bFaultState = length; bFaultState && !nArrayTest[bFaultState]; bFaultState--);
print("'Faulted at ', itoa(bFaultState)) // zero is no faults
}
I wonder if it would be any faster in your test program against find_string.
Paul
Jeff
Here is the new time information:
Line 20 (08:44:50.875):: * TEST 1 REPORT: FIND_STRING 1000x
Line 21 (08:44:50.890):: * Most recent 5 runs:
Line 22 (08:44:50.890):: * 1: 14ms
Line 23 (08:44:50.890):: * 2: 12ms
Line 24 (08:44:50.890):: * 3: 13ms
Line 25 (08:44:50.890):: * 4: 0ms
Line 26 (08:44:50.890):: * 5: 0ms
Line 27 (08:44:50.890):: *
Line 28 (08:44:50.890):: * Average run time: 13ms - over 3 tests
Line 29 (08:44:50.890):: *********************************************************
Line 30 (08:44:50.890):: *********************************************************
Line 31 (08:44:50.890):: * TEST 2 REPORT: FOR Loop 1000x
Line 32 (08:44:50.890):: * Most recent 5 runs:
Line 33 (08:44:50.890):: * 1: 911ms
Line 34 (08:44:50.890):: * 2: 909ms
Line 35 (08:44:50.890):: * 3: 909ms
Line 36 (08:44:50.890):: * 4: 0ms
Line 37 (08:44:50.906):: * 5: 0ms
Line 38 (08:44:50.906):: *
Line 39 (08:44:50.906):: * Average run time: 909ms - over 3 tests
Line 40 (08:44:50.906):: *********************************************************
I just switched it back to the way I had it, but pulling the MAX_LENGTH_ARRAY out of the 1000x loop. The average time this way was 780ms.
Jeff
Interesting. Looks like find_string wins with flying colors no?
Paul
Jeff
Oh? I don't recall using type_cast or set_array_length. Where are you using them?
Paul
Jeff
Yes, it does just loop on itself. I also added the brackets just to verify this, but did not see a change in times. Actually, if the array has a non-zero value in it, it will speed up execution time because it will stop as soon as it finds a non-zero value.
Jeff
Results:
Line 379 (14:14:13.062):: *********************************************************
Line 380 (14:14:13.062):: * TEST 1 REPORT: FIND_STRING 1000x
Line 381 (14:14:13.062):: * Most recent 5 runs:
Line 382 (14:14:13.062):: * 1: 13ms
Line 383 (14:14:13.062):: * 2: 13ms
Line 384 (14:14:13.062):: * 3: 13ms
Line 385 (14:14:13.078):: * 4: 13ms
Line 386 (14:14:13.078):: * 5: 13ms
Line 387 (14:14:13.078):: *
Line 388 (14:14:13.078):: * Average run time: 12ms - over 10 tests
Line 389 (14:14:13.078):: *********************************************************
Line 390 (14:14:13.078):: *********************************************************
Line 391 (14:14:13.078):: * TEST 2 REPORT: FOR Loop 1000x
Line 392 (14:14:13.078):: * Most recent 5 runs:
Line 393 (14:14:13.078):: * 1: 1251ms
Line 394 (14:14:13.078):: * 2: 1196ms
Line 395 (14:14:13.078):: * 3: 1654ms
Line 396 (14:14:13.078):: * 4: 1533ms
Line 397 (14:14:13.078):: * 5: 1566ms
Line 398 (14:14:13.078):: *
Line 399 (14:14:13.078):: * Average run time: 1431ms - over 10 tests
Line 400 (14:14:13.078):: *********************************************************
Jeff
P.S.
all of the insertion points happened to be in the lower positions (I think they ranged from 5 to 40). Had an insertion point gone above 50, you would see a faster time.
Paul
I've been thinking about array length with respect to this problem and was wondering if making the array one element longer than necessary and then inserting a bogus number in the last element would solve the problem. For example, if you actually had 8 zones, could you write:
As long as the find_string function is only looking for zero and one and you remember to not test the extra element, wouldn't it work?