I need to use bit operations in VBA. For example I want to set first bit in 0 second bit in 1 and so on. How can I do it?
Thanks a lot!
You could use masks.
If you want to set* the n-th bit, you can perform an Or operation of your original value and a mask filled with 0 except for the n-th position.
That way, 1100 Or 0001 will set the first bit resulting in 1101. 1100 Or 0010 will set the second bit, resulting in 1110.
If you want to unset* the n-th position, you can do the opposite. Perform an And operation on your original value with a mask filled with 1 except the n-th position.
That way, 0011 And 1110 will unset the first bit resulting in 0010, 0011 And 1101 will unset the second bit, resulting in 0001.
* Set means to turn the bit into 1. Unset means to turn the bit into 0.
Related
So I have some code that does essentially this:
REAL, DIMENSION(31) :: month_data
INTEGER :: no_days
no_days = get_no_days()
month_data = [fill array with some values]
WRITE(1000,*) (month_data(d), d=1,no_days)
So I have an array with values for each month, in a loop I fill the array with a certain number of values based on how many days there are in that month, then write out the results into a file.
It took me quite some time to wrap my head around the whole 'write out an array in one go' aspect of WRITE, but this seems to work.
However this way, it writes out the numbers in the array like this (example for January, so 31 values):
0.00000 10.0000 20.0000 30.0000 40.0000 50.0000 60.0000
70.0000 80.0000 90.0000 100.000 110.000 120.000 130.000
140.000 150.000 160.000 170.000 180.000 190.000 200.000
210.000 220.000 230.000 240.000 250.000 260.000 270.000
280.000 290.000 300.000
So it prefixes a lot of spaces (presumably to make columns line up even when there are larger values in the array), and it wraps lines to make it not exceed a certain width (I think 128 chars? not sure).
I don't really mind the extra spaces (although they inflate my file sizes considerably, so it would be nice to fix that too...) but the breaking-up-lines screws up my other tooling. I've tried reading several Fortran manuals, but while some of the mention 'output formatting', I have yet to find one that mentions newlines or columns.
So, how do I control how arrays are written out when using the syntax above in Fortran?
(also, while we're at it, how do I control the nr of decimal digits? I know these are all integer values so I'd like to leave out any decimals all together, but I can't change the data type to INTEGER in my code because of reasons).
You probably want something similar to
WRITE(1000,'(31(F6.0,1X))') (month_data(d), d=1,no_days)
Explanation:
The use of * as the format specification is called list directed I/O: it is easy to code, but you are giving away all control over the format to the processor. In order to control the format you need to provide explicit formatting, via a label to a FORMAT statement or via a character variable.
Use the F edit descriptor for real variables in decimal form. Their syntax is Fw.d, where w is the width of the field and d is the number of decimal places, including the decimal sign. F6.0 therefore means a field of 6 characters of width with no decimal places.
Spaces can be added with the X control edit descriptor.
Repetitions of edit descriptors can be indicated with the number of repetitions before a symbol.
Groups can be created with (...), and they can be repeated if preceded by a number of repetitions.
No more items are printed beyond the last provided variable, even if the format specifies how to print more items than the ones actually provided - so you can ask for 31 repetitions even if for some months you will only print data for 30 or 28 days.
Besides,
New lines could be added with the / control edit descriptor; e.g., if you wanted to print the data with 10 values per row, you could do
WRITE(1000,'(4(10(F6.0,:,1X),/))') (month_data(d), d=1,no_days)
Note the : control edit descriptor in this second example: it indicates that, if there are no more items to print, nothing else should be printed - not even spaces corresponding to control edit descriptors such as X or /. While it could have been used in the previous example, it is more relevant here, in order to ensure that, if no_days is a multiple of 10, there isn't an empty line after the 3 rows of data.
If you want to completely remove the decimal symbol, you would need to rather print the nearest integers using the nint intrinsic and the Iw (integer) descriptor:
WRITE(1000,'(31(I6,1X))') (nint(month_data(d)), d=1,no_days)
I have two questions:
What is the difference in presentation between hexadecimal ASCII And hexadecimal number?
I mean that when we say
var db 31H
How we can find out if we want to say Character a or we want to say number 31H.
Why this application goes like this?
1- a db 4 dup(41h)
2- b dw 2 dup(4141h)
I thought that this two lines will be run in the same way but in the second line when I want to see the variables they will be 8 8bits and in each one is number 41h.
But it must something wrong because dw is 2 8 bits and we are saying make 2 of 2 of 8 bits and it must be 4 8 bits not 8 8 bits.
The answer to the first question is simple: in a computer's memory, there is no ASCII, no numbers, no images ... there is just bits. 31H represents the string of bits 00110001; nothing more, nothing less.
It's only when you do something with those bits (display them to a screen, use them in a mathematical operation, etc) that you interpret it as meaning 1 (which it would in ASCII), or a (in some other character encoding), or 49 (as a decimal number), or a particular shade of blue in your colour palette.
I was working in a project and I canĀ“t use the bitwise negation with a U32 bits (Unsigned 32 bits) because when I tried to use the negation operator for example I have 1 and the negation (according to this function) was the biggest number possible with U32 and I expected the zero. My idea was working with a binary number like (110010) and I need to only negate the bits after the first 1-bit(001101). There is a way to do that in LabVIEW?
This computes the value you are looking for.
1110 --> 0001 (aka, 1)
1010 --> 0101 (aka, 101)
111 --> 000 (aka, 0) [indeed, all patterns that are all "1" will become 0]
0 --> 0 [because there are no bits to negate... maybe you want to special case this as "1"?)
Note: This is a VI Snippet. Save the .png file to your disk then drag the image from your OS into LabVIEW and it will generate the block diagram (I wrote it in LV 2016, so it works for 2016 or later). Sometimes dragging directly from browser to diagram works, but most browsers seem to strip out the EXIF data that makes that work.
Here's an alternative solution without a loop. It formats the input into its string representation (without leading zeros) to figure out how many bits to negate - call this n - and then XOR's the input with 2^n - 1.
Note that this version will return an output of 1 for an input of 0.
Using the string functions feels a bit hacky... but it doesn't use a loop!!
Obviously we could instead try to get the 'bit length' of the input using its base-2 log, but I haven't sat down and worked out how to correctly ensure that there are no rounding issues when the input has only its most significant bit set, and therefore the base-2 log should be exactly an integer, but might come out a fraction smaller.
Here's a solution without strings/loops using the conversion to float (a common method of computing floor(log_2(x))). This won't work on unsigned types.
A little background: I am writing a Visual Basic application. It will connect to an Omron Programmable Logic Controller (PLC).
When I read data from the PLC, they come as WORDs (16bits). However the PLC programmer needs to have a double-word (32bits) for a big number (bigger than what 16bits can hold). I need to be able to show that number on the screen. As mentioned, I read from the PLC as WORDs. So I can make 2 reads to get the 2 words. However they are separate.
Here's what it is: I need to show 120,000 on the screen (VB app). on the PLC, I read 2 words (in bit form):
Word#1: 1101 0100 1100 0000 (Unsigned, this equals 54464)
Word#2: 0000 0000 0000 0001
I need to put these together like this: 0000 0000 0000 0001 1101 0100 1100 0000 = 120,000
Are there any built in functions in Visual Basic that will combine these two 16bit words into into 1 Double-word? If so what is it?
Or do I have to write a function to put these two values together?
Or has someone done something like this and can provide some info for me?
I found the << and >> operands. They shift bits left and right. so I used the formula (Word2 << 16) to generate the value of Word2. then added the value of Word1.
In VBA if you want to concatenate two strings together all you need to do is use the & operator. For example:
Dim TempCombinedWord as String
TempCombinedWord = FirstWord & LastWord
If FirstWord contained Happy and LastWord contained TreeFriends. Then TempCombinedWord would then contain HappyTreeFriends.
I am making a text-based RPG game in batch, and I've been having a problem on an event in which certain weapons are supposed to do a random amount of damage between 0 and 10. Here is my code:
set /a damage=%random%/3277
echo %damage%
pause
As you can see, 3277 is approximately 32767/10. However, I keep getting 9 as the result. Can anyone help me identify what I am doing wrong? Also, is there another way I can write the code so that it has a minimum as well as a maximum? I would prefer it to be between 6 and 10, not 0 and 10.
Use modulus:
SET /A damage=%random% %% 11
This way you guarantee numbers between [0, 11[.
For such a small divisor, you will get close to a uniform distribution (assuming %random% as also a uniform distribution).