Why am I receiving an Overflow Error with my Array [duplicate] - arrays

Following code of Visual Basic 6.0 - SP2 is giving Overflow error. Can somebody explain why?
Private Sub Form_Click()
Dim Qty as Long
Qty= 290 * 113 '' 112 is working fine
MsgBox Qty
End Sub

The type of an expression is determined by its members, not by the variable it is going to be stored in.
113 gets typed as Byte.
290 gets typed as Integer because it won't fit into a byte.
As the largest of the involved types is Integer, the entire expression 290 * 113 is typed as Integer. An Integer can contain at most 32767, which is less than 290 * 113.
It therefore overflows upon multiplication, before the result is stored into a Long variable.
Explicitly type at least one of the numbers as Long:
Qty = 290& * 113

Related

Multiplication of two double-digit integer with arrays in Fortran

I have tried to write a code for multiplying two double-digit integers like ab * cd using arrays and the preliminary multiplying method. However, when I compile my code and insert any input, the output is a wrong result. I traced my code and I got an appropriate result but in compiling is something different. for example i insert 9 9 9 9 which mean 99 * 99 in this code but the result is 1210 instead of 9801.
program main
! multiplication of two double-digit integer ! array method
implicit none
integer , parameter :: size=2
integer , dimension (size)::A
integer , dimension (size)::B
integer , dimension (size+1)::C
integer , dimension (size+2)::D
integer , dimension (size+2)::E
integer :: i=0,carry1=0,carry2=0,carry3=0
do i=1,size,1
read *,A(i)
end do
do i=1,size,1
read *,B(i)
end do
do i= 3,2,-1
C(i)=B(size)*A(i-1)+carry1
if (C(i)>9)then
C(i)=mod (C(i),10)
carry1 = C(i)/10
else
carry1=0
end if
end do
C(1)=carry1
D(4)=0
do i=3,2,-1
D(i)=B(size-1)*A(i-1)+carry2
if (D(i)>9)then
D(i)=mod (D(i),10)
carry2= D(i)/10
else
carry2=0
end if
end do
D(1)=carry2
do i=4,2,-1
E(i)=D(i)+C(i-1)+carry3
if (E(i)>9) then
E(i)=mod (E(i),10)
carry3=1
else
carry3=0
end if
end do
E(1)=D(1)+carry3
do i=4,1,-1
print*,E(i)
end do
end program main

Converting byte array to single from binary file

UPDATED - I added 2 screen shots with 0.00 in the data and one with 1234.56 in the data
I am using an old VB6 set of code as 95% works to read a text file that gets converted and stored in MS SQL. The strings are all good however there are numbers mixed into the text binary file that I haven't figured out how to read. The original application the numbers are all currency however the hex dump of the numbers looks to be 4 byte numbers.
Either way I am not sure how to read the numbers into a local variable. Maybe I am not starting at the correct place in the data. In the example below I am starting at the <160>.
Here is a dump of the part of the binary file with 0.00 in the data:
Here is a dump of the part of the binary file with 1234.56 in the data:
Note the arrow point to where the data changed.
This is my last try but that doesnt work either.
Function ReadFloat(f As Integer, Optional ShowDB As Boolean = False) As String
On Error GoTo 0
Dim c As Single
Dim S(4) As Byte
Dim x As Integer
Dim flt As Single
Get f, , S
For x = 1 To 4
Debug.Print x & " " & S(x) & " " & Hex(S(x)); "='" & Chr(S(x)) & "'"
Next x
CopyMemory flt, S, 4
My initial inspection suggests that the bytes starting:
40 E2 01
are what you're looking for. These are stored little endian, so 01E240 is hex for 123456 in decimal. So my guess would be 32 bit integers (4 byte long type). You can test this by using -0.01 as a value, this should give:
... FF FF FF FF ...
in the file.
If you're only interested in reading just these values then you can read and discard the first x values. Something like:
Dim yDiscard(123) As Byte
...
Get #1, ,yDiscard
Or alternatively, just seek to the position first before reading:
Seek #1, 123
To work out what byte values to expect in general, I found the following to be useful. Just run the code in a module:
Sub main()
Dim lValue As Long
Dim cValue As Currency
Dim nValue As Single
Dim dValue As Double
Dim sValue As String
Dim vValue As Variant
lValue = 123456
cValue = 1234.56
nValue = 1234.56
dValue = 1234.56
sValue = "1234.56"
vValue = CDec(1234.56)
Open "c:\test1.bin" For Binary As 1
Open "c:\test2.bin" For Binary As 2
Open "c:\test3.bin" For Binary As 3
Open "c:\test4.bin" For Binary As 4
Open "c:\test5.bin" For Binary As 5
Open "c:\test6.bin" For Binary As 6
Put #1, , lValue
Put #2, , cValue
Put #3, , nValue
Put #4, , dValue
Put #5, , sValue
Put #6, , vValue
Close #1
Close #2
Close #3
Close #4
Close #5
Close #6
End Sub
You can then inspect each file in a hex editor (I use MadEdit but anything will do).
It's probably useful to also try simple values like 1.00, 2.00, 10.00, -1.00 and see how the bytes differ each time.
This may also be informative (fairly in depth):
http://www.codeguru.com/vb/gen/vb_misc/algorithms/article.php/c7495/How-Visual-Basic-6-Stores-Data.htm
And to actually answer the question, something like the following will read a 32 bit integer and convert to currency:
Function ReadAmount(iFileHandle As Integer, lFileBytePosition As Long) As Currency
Dim lValue As Long
Seek #iFileHandle, lFileBytePosition
Get #iFileHandle, , lValue
ReadAmount = CCur(lValue) / 100
End Function
There's no need for an intermediate byte array.
True floating point are bad when using currency, so actually your number is an integer with fixed point.
First : put them in an integer variable (type Long)
Second : divide by 100 to get back the decimal !
Straightforward method to convert it to single:
Dim S(4) As Byte 'your 4 bytes, like (1)=&H40, (2)=&HE2 (3)=&H01, (4)=&H00
Dim Buffer As Long
Buffer = S(4) * 16777116 Or S(3) * 65536 Or S(2) * 256 Or S(1)
Dim flt As Single
flt = Buffer / 100

Using CAST and bigint

I am trying to understand what does this statement does
SUM(CAST(FILEPROPERTY(name, 'SpaceUsed') AS bigint) * 8192.)/1024 /1024
Also why is there a dot after 8192? Can anybody explain this query bit by bit. Thanks!
FILEPROPERTY() returns an int value. Note that the SpaceUsed property is not in bytes but in "pages" - and in SQL Server a page is 8KiB, so multiplying by 8192 to get the size in KiB is appropriate.
I've never encountered a trailing dot without fractional digits before - the documentation for constants/literals in T-SQL does not give an example of this usage, but reading it implies it's a decimal:
decimal constants are represented by a string of numbers that are not enclosed in quotation marks and contain a decimal point.
Thus multiplying the bigint value by a decimal would yield a decimal value, which may be desirable if you want to preserve fractional digits when dividing by 1024 (and then 1024 again), though it's odd that those numbers are actually int literals, so the operation would just be truncation-division.
I haven't tested it, but you could try just this:
SELECT
SUM( FILEPROPERTY( name, 'SpaceUsed' ) ) * ( 8192.0 / 10485760 ) AS TotalGigabytes
FROM
...
If you're reading through code and you need to do research to understand what it's doing - do a favour for the next person who reads the code by adding an explanatory comment to save them from having to do research, e.g. "gets the total number of 8KiB pages used by all databases, then converts it to gigabytes".
The dot . after an Integer converts it implicitly to decimal value. This is most likely here to force the output to also be decimal (not an integer). In this case you only need one part of the operation to be converted to force the output to be in that type.
This probably has to do with bytes/pages since the numbers 8192 and 1024 (most likely for converting to larger unit). One could also imply this by the value of property which indicates how much space is being used by a file.
A page fits within 8kB which means that multiplying pages value by 8192 does convert the output to bytes being used. Then division two times by 1024 succesfully converts the output to gigabytes.
Explanation on functions used:
FILEPROPERTY returns a value for a file name which is stored within database. If a file is not present, null value is returned
CAST is for casting the value to type bigint
SUM is an aggregate function used in a query to sum values for a specified group

Why character d & f ignored for oracle Number field in where condition?

As I mentioned in question title,character d & f are ignored(?) in Oracle where condition
Below query runs without any error
select employee_id from employees where employee_id > 106f
But if I specify other than d or f after 106 ORA-00933: SQL command not properly ended error will be thrown because employee_id is of datatype Number
Why this Strange behaviour?? That to it happens for only single letter after number,if I specify 106df it throws error(which is correct)
According to Oracle docs, d and f are allowable suffixes for numeric literals, denoting 64-bit (double) and 32-bit (float) binary floating-point types. In your case, the type doesn't make any difference (it probably just gets converted back to integer for the comparison, and with no loss of accuracy because 106 is small enough to be represented exactly as a float), so it looks like nothing is happening. Other letters, and 106df, aren't allowed by the syntax. (e is allowed, but only if followed by a number.)

MATLAB sort function yields tampered results

I have a vector of 126 elements which is usually correctly sorted; however, I always sort it to make sure everything is okay.
The problem is that: when the array is already sorted, performing a sort would destroy the original values of the array.
I attached the array in a csv file and executed the script below, where I insert the vector in the first column of 'a' then sort it in the second then check for any differences in the third column.
a = csvread('a.csv')
a(:,2)=sort(a(:,1))
a(:,3)=a(:,2)-a(:,1)
result=sum(a(:,3).^2)
You could easily see that the first two columns aren't identical, and the third column has some none zero values.
Syntax for array
a = [17.4800
18.6800
19.8800
21.0800
22.2800
23.4800
24.6800
25.8800
27.0800
28.2800
29.4800
30.6800
46.1600
47.3600
48.5600
49.7600
50.9600
52.1600
53.3600
54.5600
55.7600
56.9600
58.1600
59.3600
74.8400
76.0400
77.2400
78.4400
79.6400
80.8400
103.5200
104.7200
105.9200
107.1200
108.3200
109.5200
110.7200
111.9200
113.1200
114.3200
115.5200
116.7200
132.2000
133.4000
134.6000
135.8000
137.0000
138.2000
139.4000
140.6000
141.8000
143.0000
144.2000
145.4000
165.4200
166.6200
167.8200
169.0200
170.2200
171.4200
172.6200
173.8200
175.0200
176.2200
177.4200
178.6200
179.9300
181.1300
182.3300
183.5300
184.7300
185.9300
187.1300
188.3300
189.5300
201.3700
202.5700
203.7700
204.9700
206.1700
207.3700
236.1100
237.3100
238.5100
239.7100
240.9100
242.1100
243.3100
244.5100
245.7100
246.9100
248.1100
249.3100
239.8400
241.0400
242.2400
276.9900
278.1900
279.3900
280.5900
281.7900
282.9900
284.1900
285.3900
286.5900
287.7900
288.9900
290.1900
277.8200
279.0200
280.2200
281.4200
282.6200
283.8200
285.0200
286.2200
287.4200
288.6200
289.8200
291.0200
291.0700
292.2700
293.4700
295.6900
296.8900
298.0900];
Your original vector is unfortunately not sorted. Therefore, sorting this result will obviously not give you what the original vector is supposed to be as the values that were out of order will become in order.
You can check this by using diff on the read in vector from the CSV file and seeing if there are any negative differences. diff takes the difference between the (i+1)th value and the ith value and if your values are monotonically increasing, you should get positive differences all around. We can see which locations are affected by finding values in the difference that are negative:
a = csvread('a.csv');
ind = find(diff(a) < 0);
We get:
>> ind
ind =
93
108
This says that locations 93 and 108 are where the out of order starts. Locations 94 and 109 is where it actually happens. Let's check out portions 90 - 110 of your vector to be sure:
>> a(90:110)
ans =
245.7100 % 90
246.9100 % 91
248.1100 % 92
249.3100 % 93
239.8400 %<-------
241.0400
242.2400
276.9900
278.1900
279.3900
280.5900
281.7900
282.9900
284.1900
285.3900
286.5900
287.7900 % 106
288.9900 % 107
290.1900 % 108
277.8200 % <------
279.0200
As you can see, locations 93 and 108 take a dip in numerical value, and so if you tried sorting the result then taking the difference, you'll notice that locations 1 up to 93 will exhibit a difference of 0, but after location 93, that's when it becomes unequal.
I'm frankly surprised you didn't see that they're out of order because your snapshot clearly shows there's a decrease in value on the left column towards the top of the snapshot.
Therefore, either check your data to see if you have input it correctly, or modify whatever process you're working on to ensure that it can handled unsorted data.

Resources