Decimal places accuracy in REDUCE operator - math

In my below code, I declared sum and lt_req-dmbtr as dmbtr, but in the output it is not showing the decimal values and output is also less than 2 or 3 signs than the expected
DATA(total) = REDUCE dmbtr( INIT sum = 0 FOR wa IN lt_req WHERE ( gsber = <fs_ba_det>-gsber AND gjahr = 2020 ) NEXT sum = sum + conv dmbtr( wa-dmbtr ) ).
Sometimes it is thworing the error
CX_SY_ARITHMETIC_OVERFLOW

The sum variable type is qualificative here, not the wa-dmbtr you convert from.
Excerpt from REDUCE help:
The declarations after INIT create local variables x1, x2
...
After the full evaluation, the content of the first variable x1 or the memory area pointed to by the first field symbol is assigned to the temporary result of the expression of type type in accordance with the assignment rules.
And in your snippet your sum is zero, so it is Integer and it limits all other types.
The correct form of REDUCE to achieve your requirement:
TYPES:
BEGIN OF ty_product,
product TYPE char10,
price TYPE dmbtr,
group TYPE char10,
END OF ty_product,
tt_products TYPE STANDARD TABLE OF ty_product WITH EMPTY KEY.
DATA(t_prod) =
VALUE tt_products(
( product = 'C0001' price = '1.005' group = 'commodities' )
( product = 'C0002' price = '245.48575' group = 'crude' )
( product = 'C0003' price = '500.05' group = 'crude' )
( product = 'C0004' price = '32' group = 'commodities' )
).
DATA(total) = REDUCE dmbtr( INIT sum = CONV dmbtr( 0 ) FOR wa IN t_prod WHERE ( group = 'crude' ) NEXT sum = sum + wa-price ).
WRITE total.
That will give 745.53575 as a result.

Related

Scilab - Finding the average of randomly generated numbers with different indices

Say I have a function that generates random integers between say (1,10).
Then, I define a (for loop) which has 5 iterations.
This (for loop) calls the function defined above, and then it checks the value of the integer generated by the function. Depending on the value of the integer, the variable "cost" is decided.
function integer = UniformInt(a, b)
integer = min( floor( rand()*(b-a) ) + a , b);
endfunction
for i=1:5
x(i) = UniformInt(1,10);
if (x(i)<4) then
cost(i) = 15;
elseif (4<=x(i) && x(i)<=8) then
cost(i) = 27;
else
cost(i) = 35;
end
end
Now, when I run that and find x, say the values generated are:
5.
9.
5.
2.
2.
And so, the different cost values will be:
27.
35.
27.
15.
15.
This is all good so far. Now, what I want to do with these results is:
Check how many times each value of x appeared. I can do this via Scilab's tabul function:
9. 1.
5. 2.
2. 2.
Now, what I really want to code is:
x=9 only showed up once, so, the average of cost is 35/1 = 35.
x=5 showed up twice, so, the average of cost is (27+27)/2 = 27.
x=2 showed up twice, so, the average of cost is (15+15)/2 = 15.
How would I do that?
For posterity, a code in which the answer provided by user #Stéphane Mottelet would be useful (because my code above is trivial) is as follows:
function integer = UniformInt(a, b)
integer = min( floor( rand()*(b-a) ) + a , b);
endfunction
for i=1:5
x(i) = UniformInt(1,10);
if (x(i)<4) then
cost(i) = 15*rand();
elseif (4<=x(i) && x(i)<=8) then
cost(i) = 27*rand();
else
cost(i) = 35*rand();
end
end
Now the cost values are multiplied by a random number, and so,
if the value of say x=10 showed up 2 times, the average cost when x=10 will not simply be (35+35)/2.
I would do like this, but the answer is quite trivial since for now the value of cost is the same for a given x value (I suppose your real application draws random values of cost)
t = tabul(x);
for k = 1:size(t,1)
avg(k) = mean(cost(x == t(k)));
end

How to use the "6" char code in overloading insertion function on Scilab?

In the Help Documentation of Scilab 6.0.2, I can read the following instruction on the Overloading entry, regarding the last operation code "iext" showed in this entry's table:
"The 6 char code may be used for some complex insertion algorithm like x.b(2) = 33 where b field is not defined in the structure x. The insertion is automatically decomposed into temp = x.b; temp(2) = 33; x.b = temp. The 6 char code is used for the first step of this algorithm. The 6 overloading function is very similar to the e's one."
But I can't find a complete example on how to use this "char 6 code" to overload a function. I'm trying to use it, without success. Does anyone have an example on how to do this?
The code bellow creates a normal "mlist" as a example. Which needs overloading functions
A = rand(5,3)
names = ["colA" "colB" "colC"]
units = ["ft" "in" "lb"]
M = mlist(["Mlog" "names" "units" names],names,units,A(:,1),A(:,2),A(:,3))
Following are the overload functions:
//define display
function %Mlog_p(M)
n = size(M.names,"*")
formatStr = strcat(repmat("%10s ",1,n)) + "\n"
formatNum = strcat(repmat("%0.10f ",1,n)) + "\n"
mprintf(formatStr,M.names)
mprintf(formatStr,M.units)
disp([M(M.names(1)),M(M.names(2)),M(M.names(3))])
end
//define extraction operation
function [Mat]=%Mlog_e(varargin)
M = varargin($)
cols = [1:size(M.names,"*")] // This will also work
cols = cols(varargin($-1)) // when varargin($-1) = 1:1:$
Mat = []
if length(varargin)==3 then
for i = M.names(cols)
Mat = [Mat M(i)(varargin(1))]
end
else
for i=1:size(M.names(cols),"*")
Mat(i).name = M.names(cols(i))
Mat(i).unit = M.units(cols(i))
Mat(i).data = M(:,cols(i))
end
end
endfunction
//define insertion operations (a regular matrix into a Mlog matrix)
function ML=%s_i_Mlog(i,j,V,M)
names = M.names
units = M.units
A = M(:,:) // uses function above
A(i,j) = V
ML = mlist(["Mlog" "names" "units" names],names,units,A(:,1),A(:,2),A(:,3))
endfunction
//insertion operation with structures (the subject of the question)
function temp = %Mlog_6(j,M)
temp = M(j) // uses function %Mlog_e
endfunction
function M = %st_i_Mlog(j,st,M)
A = M(:,:) // uses function %Mlog_e
M.names(j) = st.name // uses function above
M.units(j) = st.unit // uses function above
A(:,j) = st.data // uses function above
names = M.names
units = M.units
M = mlist(["Mlog" "names" "units" names],names,units,A(:,1),A(:,2),A(:,3))
endfunction
The first overload (displays mlist) will show the matrix in the form of the following table:
--> M
M =
colA colB colC
ft in lb
0.4720517 0.6719395 0.5628382
0.0623731 0.1360619 0.5531093
0.0854401 0.2119744 0.0768984
0.0134564 0.4015942 0.5360758
0.3543002 0.4036219 0.0900212
The next overloads (extraction and insertion) Will allow the table to be access as a simple matrix M(i,j).
The extraction function Will also allow M to be access by column, which returns a structure, for instance:
--> M(2)
ans =
name: "colB"
unit: "in"
data: [5x1 constant]
The last two functions are the overloads mentioned in the question. They allow the column metadata to be changed in a structure form.
--> M(2).name = "length"
M =
colA length colC
ft in lb
0.4720517 0.6719395 0.5628382
0.0623731 0.1360619 0.5531093
0.0854401 0.2119744 0.0768984
0.0134564 0.4015942 0.5360758
0.3543002 0.4036219 0.0900212

Lua module for calculating the molar mass of chemical compounds

I have been using (or attempting to, most of the modules I have I have borrowed from other Wikis as my understanding of Lua is limited at best) Lua-based modules and their invoking templates (i.e., the ones that invoke them with {{#invoke:}}) on my Wiki for some time and I have an infobox for chemical compounds (my Chembox) which includes inputs for the numbers of atoms of each chemical element present in the compound (i.e., those numbers used in the compound's molecular formula) and the molar mass of the compound. I was thinking, since it is possible to calculate the molar mass of the compound based on its molecular formula it might be possible to create a Lua module that can do this automatically for me, eliminating the need for me to input the molar mass myself into these infoboxes.
So my question is basically, how do I do this?
Research
My background is in mathematics, so I felt the most straight-forward way of doing this is to set up two vectors, A and B, and perform a dot-product between them. A would contain the user-defined variables, namely, those provided to the template that invokes the module. For example, say we were talking about ethanol (C2H6O) then the template may look like:
{{Molar mass calculator
|C = 2
|H = 6
|O = 1
}}
. B would contain the average atomic mass of each element in grams per mol (g/mol). This vector will be self-provided (i.e., by me, I have a list of 84 elements found in sufficient quantities in nature for these standard atomic weights to be available, with their standard atomic weights also listed. So I will provide them in the Lua code if you just show me where to add them to the code.).
I have looked up dot products in Lua to see if this is possible and how to do them and found this code (http://rosettacode.org/wiki/Dot_product#Lua):
function dotprod(a, b)
local ret = 0
for i = 1, #a do
ret = ret + a[i] * b[i]
end
return ret
end
print(dotprod({1, 3, -5}, {4, -2, 1}))
I believe this is what you are looking for :)
Populate the "AtomicWeightLookup" table with your own values.
There is an example call to the "Calculate" function at the end of the program.
local AtomicWeightLookup = {
C = 12.01,
H = 1.001,
O = 16
}
local function Calculate(Input)
-- Input Example: {C = 2, H = 6, O = 1}
local Result = 0
-- Iterate through Input table
for Element,Quantity in next,Input do
-- If element is not found in table, assume 0 weight.
local AtomicWeight = AtomicWeightLookup[Element] or 0
-- Multiply
Result = Result + Quantity * AtomicWeight
end
return Result
end
-- EXAMPLE
print(Calculate({C = 2, H = 6, O = 1}))
Via emailing the Wikitech-I mailing list (wikitech-I#lists.sourceforge.net) I received an answer. Module:Molar mass calculator is to have the code (the round function is designed to round the end result to the nearest three decimal places, as I later decided that I wanted this capability too):
local p = {};
function p.calc(frame)
local atomicWeights = mw.loadData( 'Module:Standard atomic weight' )
local total = 0
for element, quantity in pairs( frame:getParent().args ) do
if quantity ~= "" then
local atomicWeight = atomicWeights[element] or error( 'Element "' .. element .. '" is not known. Please add it to [[Module:Standard atomic weight]] if it\'s not a typo.' )
quantity = tonumber( quantity ) or error( 'Quantity for ' .. element .. ' is not a number.' )
total = total + atomicWeight * quantity
end
end
function round(num, idp)
local mult = 10^(idp or 0)
return math.floor(num * mult + 0.5) / mult
end
return round(total,3)
end
return p
Module:Standard atomic weight has the code:
local M = {}
M['Ag'] = 107.8682 -- Silver (Ag)
M['As'] = 74.921595 -- Arsenic (As)
M['Au'] = 196.966569 -- Gold (Au)
M['B'] = 10.8135 -- Boron (B)
M['Ba'] = 137.327 -- Barium (Ba)
M['Bi'] = 208.9804 -- Bismuth (Bi)
M['Br'] = 79.904 -- Bromine (Br)
M['C'] = 12.0106 -- Carbon (C)
M['Ca'] = 40.078 -- Calcium (Ca)
M['Cl'] = 35.4515 -- Chlorine (Cl)
M['Co'] = 58.933194 -- Cobalt (Co)
M['Cu'] = 63.546 -- Copper (Cu)
M['F'] = 18.998403163 -- Fluorine (F)
M['Fe'] = 55.845 -- Iron (Fe)
M['Ga'] = 69.723 -- Gallium (Ga)
M['H'] = 1.007975 -- Hydrogen (H)
M['Hg'] = 200.592 -- Mercury (Hg)
M['I'] = 126.90447 -- Iodine (I)
M['K'] = 39.0983 -- Potassium (K)
M['Li'] = 6.9675 -- Lithium (Li)
M['Mg'] = 24.3055 -- Magnesium (Mg)
M['Mn'] = 54.938044 -- Manganese (Mn)
M['N'] = 14.006855 -- Nitrogen (N)
M['Na'] = 22.98976928 -- Sodium (Na)
M['Ni'] = 58.6934 -- Nickel (Ni)
M['O'] = 15.9994 -- Oxygen (O)
M['P'] = 30.973761998 -- Phosphorus (P)
M['Pb'] = 207.2 -- Lead (Pb)
M['Pt'] = 195.084 -- Platinum (Pt)
M['S'] = 32.0675 -- Sulfur (S)
M['Se'] = 78.971 -- Selenium (Se)
M['Sr'] = 87.62 -- Strontium (Sr)
M['Tl'] = 204.3835 -- Thallium (Tl)
M['Zn'] = 65.38 -- Zinc (Zn)
return M
and Template:Molar mass calculator:
{{#invoke:Molar mass calculator|calc}} g/mol

Length of nested array lua

I am having trouble figuring out how to get the length of a matrix within a matrix within a matrix (nested depth of 3). So what the code is doing in short is... looks to see if the publisher is already in the array, then it either adds a new column in the array with a new publisher and the corresponding system, or adds the new system to the existing array publisher
output[k][1] is the publisher array
output[k][2][l] is the system
where the first [] is the amount of different publishers
and the second [] is the amount of different systems within the same publisher
So how would I find out what the length of the third deep array is?
function reviewPubCount()
local output = {}
local k = 0
for i = 1, #keys do
if string.find(tostring(keys[i]), '_') then
key = Split(tostring(keys[i]), '_')
for j = 1, #reviewer_code do
if key[1] == reviewer_code[j] and key[1] ~= '' then
k = k + 1
output[k] = {}
-- output[k] = reviewer_code[j]
for l = 1, k do
if output[l][1] == reviewer_code[j] then
ltable = output[l][2]
temp = table.getn(ltable)
output[l][2][temp+1] = key[2]
else
output[k][1] = reviewer_code[j]
output[k][2][1] = key[2]
end
end
end
end
end
end
return output
end
The code has been fixed here for future reference: http://codepad.org/3di3BOD2#output
You should be able to replace table.getn(t) with #t (it's deprecated in Lua 5.1 and removed in Lua 5.2); instead of this:
ltable = output[l][2]
temp = table.getn(ltable)
output[l][2][temp+1] = key[2]
try this:
output[l][2][#output[l][2]+1] = key[2]
or this:
table.insert(output[l][2], key[2])

Classic ASP : what's wrong with my code to convert quantity from dozen to piece (eg. 10.3 dozen = 123 pieces)

What i want is to retrieve quantity in database from piece and covert it to dozen. Then input as dozen and convert back to pieces and save to database again.
when I input data eg. 10.3, it should convert to 123 piece for me ((10 * 12) + 3). My code work well without my "If clause" but only when data was "single" type. It made error when I input integer number, so I added "If.." statement to check it first which is now the output was correct for Integer but incorrect when I input single number.
I have this code..
Function DzToPcs(val)
'If CLng(val) = val then <-- not work
'if Fix(val) <> val then <-- work but the output was not correct when input single type number.
if Int(vInt) = vInt then <-- work but the output was not correct when input single type number.
DztoPcs = val * 12
else
strInt = Cstr(val)
a = Split(strInt,".")
dz = a(0)
pcs = a(1)
getdz = Cint(dz)
getpcs = Cint(pcs)
DztoPcs = (getdz * 12) + getpcs
end if
I'm not sure what's wrong with your if statements (my VBScript is a little rusty), but you could try this alternative:
Function DzToPcs(val)
strInt = Cstr(val)
a = Split(strInt,".")
dz = a(0)
if UBound(a) > 0 then
pcs = a(1)
getdz = Cint(dz)
getpcs = Cint(pcs)
DztoPcs = (getdz * 12) + getpcs
else
DztoPcs = dz * 12
end if
end function

Resources