FileMaker Divide by Zero Error - filemaker

I have a Calculation field in my Results table that will calculate the coursework_percent based on a student's submission of classwork, homework, quiz, project and participation. The code for the Calculation field is this:
Sum ( Coursework_Results_Classwork::mark ) / If ( Sum ( Coursework_CR_Classwork::max_mark ) ≠ 0 ; Sum ( Coursework_CR_Classwork::max_mark ) - Sum ( Coursework_Results_Classwork::reduce_max ) ; 1 ) * Coursework_Weighting::classwork_w
+
Sum ( Coursework_Results_Homework::mark ) / If ( Sum ( Coursework_CR_Homework::max_mark ) ≠ 0 ; Sum ( Coursework_CR_Homework::max_mark ) - Sum ( Coursework_Results_Homework::reduce_max ) ; 1 ) * Coursework_Weighting::homework_w
+
Sum ( Coursework_Results_Quiz::mark ) / If ( Sum ( Coursework_CR_Quiz::max_mark ) ≠ 0 ; Sum ( Coursework_CR_Quiz::max_mark ) - Sum ( Coursework_Results_Quiz::reduce_max ) ; 1 ) * Coursework_Weighting::quiz_w
+
Sum ( Coursework_Results_Project::mark ) / If ( Sum ( Coursework_CR_Project::max_mark ) ≠ 0 ; Sum ( Coursework_CR_Project::max_mark ) - Sum ( Coursework_Results_Project::reduce_max ) ; 1 ) * Coursework_Weighting::project_w
+
Sum ( Coursework_Results_Participation::mark ) / If ( Sum ( Coursework_CR_Participation::max_mark ) ≠ 0 ; Sum ( Coursework_CR_Participation::max_mark ) - Sum ( Coursework_Results_Participation::reduce_max ) ) * Coursework_Weighting::participation_w
The idea behind the code is this:
If a student did not submit a coursework due to valid reason, he should not be penalised. Hence, his maximum mark should be adjusted accordingly. I used reduce_max to reduce his otherwise maximum possible score.
My bug is this:
If a particular category (e.g. homework) has only 1 assignment and the student did not submit with valid reason(hence an empty field), the calculated field will have a division by zero error. I cannot use a zero because zero is used for non-submission without valid reason. I suspect that the bug lies in my If condition testing for ≠ 0. An empty field is not considered a zero.
Can someone help me out? Thanks.
I amended pft's answer to solve my problem. The bug was not really due to empty field. Instead, it occurs when I use reduce_max such that the maximum of the coursework becomes zero. My solution is this:
Let ([
sumOfClasswork = Sum ( Coursework_Results_Classwork::mark );
sumOfHomework = Sum ( Coursework_Results_Homework::mark );
sumOfQuiz = Sum ( Coursework_Results_Quiz::mark );
sumOfProject = Sum ( Coursework_Results_Project::mark );
sumOfParticipation = Sum ( Coursework_Results_Participation::mark );
classworkMax = Sum ( Coursework_CR_Classwork::max_mark );
homeworkMax = Sum ( Coursework_CR_Homework::max_mark );
quizMax = Sum ( Coursework_CR_Quiz::max_mark );
projectMax = Sum ( Coursework_CR_Project::max_mark );
participationMax = Sum ( Coursework_CR_Participation::max_mark );
classworkReductions = Sum ( Coursework_Results_Classwork::reduce_max );
homeworkReductions = Sum ( Coursework_Results_Homework::reduce_max );
quizReductions = Sum ( Coursework_Results_Quiz::reduce_max );
projectReductions = Sum ( Coursework_Results_Project::reduce_max );
participationReductions = Sum ( Coursework_Results_Participation::reduce_max );
// if coursework maximum after reduction is zero, 1 is returned to avoid a division by zero error
classworkRedMax = If ( classworkMax - classworkReductions <> 0 ; classworkMax - classworkReductions ; 1 );
homeworkRedMax = If ( homeworkMax - homeworkReductions <> 0 ; homeworkMax - homeworkReductions ; 1 );
quizRedMax = If ( quizMax - quizReductions <> 0 ; quizMax - quizReductions ; 1 );
projectRedMax = If ( projectMax - projectReductions <> 0 ; projectMax - projectReductions ; 1 );
participationRedMax = If ( participationMax - participationReductions <> 0 ; participationMax - participationReductions ; 1 );
classworkWeight = Coursework_Weighting::classwork_w;
homeworkWeight = Coursework_Weighting::homework_w;
quizWeight = Coursework_Weighting::quiz_w;
projectWeight = Coursework_Weighting::project_w;
participationWeight = Coursework_Weighting::participation_w
];
// finally the computation of coursework ;)
sumOfClasswork / classworkRedMax * classworkWeight
+
sumOfHomework / homeworkRedMax * homeworkWeight
+
sumOfQuiz / quizRedMax * quizWeight
+
sumOfProject / projectRedMax * projectWeight
+
sumOfParticipation / participationRedMax * participationWeight
)

I believe the IsEmpty function should help you out here. If I understand your intention correctly, you could use this code segment:
Let ([
sumOfMarks = Sum ( Coursework_Results_Classwork::mark );
sumOfMaxs = Sum ( Coursework_CR_Classwork::max_mark );
sumOfReductions = Sum ( Coursework_Results_Classwork::reduce_max );
firstMax = Coursework_CR_Classwork::max_mark;
theWeight = Coursework_Weighting::classwork_w
];
Case (
// The case where the student has at least one valid,
// positively-scored assignment
sumOfMaxs > 0 ; sumOfMarks / (sumOfMaxs - sumOfReductions) ;
// The case where there is only one related record for max_mark
// and it is empty
IsEmpty ( firstMax ) ; 1
) * theWeight
)

Related

Why does loop crash and and not print? Unity3D

Given a cubic space, this function searches for the next large empty space, places a marker there, and then quits.
However, the function doesn't even print the check message that exists prior to the loops starting, so i don't know how to debug it. The checking starts at 0,0,0 and spaces outside the voxel are returned as true, so it should default all the first loops and send messages back. The unity.exe process jams and i have to abort it.
Why doesn't it print? What else is wrong with it? Even if it is slow, i should be able to track progress within the loops? why wouldn't it?
function findvoidable() //find void space in voxel volume
{
var step = dist+1;
print("start"); WaitForFixedUpdate(); //this doesnt print
for ( var k : int = 0; k < mesher.PNGpaths.Length ; k+=step/2)
for ( var j = 0; j < mesher.tex.height ; j+=step/2)
for ( var i = 0; i < mesher.tex.width ; i+=step/2){
print("in schema");WaitForFixedUpdate();
if (wst( i , j , k )==false )
if (wst( i+step,j ,k )==false )
if (wst( i-step,j ,k )==false )
if (wst( i ,j+step,k )==false )
if (wst( i ,j-step,k )==false )
if (wst( i ,j ,k+step )==false )
if (wst( i ,j ,k-step )==false )
{
var cnt=0;
for ( var x = i-step; x < i+step ; x+=1)
for ( var y = j-step; y < j+step ; y+=1)
for ( var z = k-step; z < k+step ; z+=1)
{
if ( wst( x , y , z ) == false )
cnt+=1;
}
if ( cnt >= step*step*step-3 )
{
refCube.transform.position=Vector3(i,j,k);
break;break;break;break;break;break;
}
else
{
WaitForFixedUpdate();
refCube.transform.position=Vector3(i,j,k);
}
}
}
}
WaitForFixedUpdate is a Coroutine and is not supposed to be run like a normal method.
Instead, try "yield" statement:
yield WaitForFixedUpdate();
More info: https://docs.unity3d.com/ScriptReference/Coroutine.html

I am trying to pass a variable from a procedure as input into another procedure netlogo

I am trying to pass the formBuyerAggressiveness into a bidTargetPrice procedure. It is giving a "Expected reporter" error message. Here is my code thus far.
to bidTargetPrice [tradeID]
let buyerAggressiveness [formBuyerAggresiveness] of tradeID
; if ( buyerAggresiveness <= 1 ) [
ifelse (- 1 < buyerAggresiveness) and (buyerAggresiveness <= 0)
[report equilibriumPrice * (1 - ( ( ( e ^ (- buyerAggresiveness * theta ) ) - 1) / (e ^ theta - 1) ) )
]
[report equilibriumPrice + ( (value - equilibriumPrice) * ( ( (e ^ (buyerAggresiveness * theta) ) - 1 ) / ( (e ^ theta) - 1) ) )
]
; ]
The following is the procedure which I call in the above procedure. I intend to pass the buyers aggressiveness parameter into a procudere that helps form the price.
to formBuyerAggresiveness
;define some local parameters
ifelse (transactionPrice > 0.0 )
[ ifelse (bidTargetPrice >= transactionPrice)
[ let desiredAggressiveness ( ( (1 - C2 ) * rshout) - C1 ) ;rshout is the degree of aggressiveness that would form a price equal to the last bid
report buyerAggressiveness (degreeOfAggressiveness + B1 * (desiredAggressiveness - degreeOfAggressiveness) ) ;degreeOfAggressiveness is a random of individual trader aggressiveness from -1 to 1 range. *defined during init user/buyer
]
[ let desiredAggressiveness ( ( (1 + C2 ) * rshout) + C1 ) ;buyer must be more aggresive
report degreeOfAggressiveness + B1 * (desiredAggressiveness - degreeOfAggressiveness)
]
]
[ if (bid?) and (bidTargetPrice <= bestBid)
[let desiredAggressiveness ( ( (1 + C2 ) * rshout) + C1 )
report degreeOfAggressiveness + B1 * (desiredAggressiveness - degreeOfAggressiveness)
]
]
end
The problem is with the line let buyerAggressiveness [formBuyerAggresiveness] of tradeID. There error message is telling you that [formBuyerAggresiveness] is not a reporter. The phrase [attrA] of myagent only works when myagent (i) is an agent and (ii) has this attribute.
To fix this, you have at least two choices.
give your agent an aggressiveness attribute and write a procedure to set it, so you can then access it with [aggressiveness] of myagent, or
write a reporter that takes an agent as an argument and returns an aggressiveness value for that agent

Round to the closest .25

Does anyone know of a way to round to the closest .25 in t-sql? Currently I am rounding down using
floor(value * 4)/4
My client is changing their algorithm and wants to do a midpoint round to the closest quarter. If the value is less than .125 round to 0.00, if the value is greater than or equal to .125 round up to .25.
use ROUND(value/25, 2) * 25 like this:
Example1:
DECLARE #value DECIMAL(18, 2)
SET #value = 1.126
SELECT CAST(ROUND(#value/25, 2) * 25 as numeric(18,2)) AS rounded_val
Output:
1.25
Example2:
DECLARE #value DECIMAL(18, 2)
SET #value = 1.124
SELECT CAST(ROUND(#value/25, 2) * 25 as numeric(18,2)) AS rounded_val
Output:
1.00
select Sample,
Round( ( Sample + Sign( Sample ) * 0.125 ) * 4, 0, 1 ) / 4.0 as Rounded
from ( values ( 0.0 ), ( 0.1 ), ( 1.125 ), ( 0.25 ), ( 10.5 ),
( -0.75 ), ( -0.875 ), ( -1.12 ), ( -1.125 ) )
as Samples( Sample )
Note that ROUND can be used to truncate the fractional part of a value regardless of the sign. FLOOR will always return a value equal to or less than the original value, which can be problematic when the value is negative.
I needed to round to an arbitrary precision & rounding strategy.
rounding to *.25
DECLARE #roundamt DECIMAL(16,2) = .25, #value DECIMAL(18, 2) = 1.7688
SELECT ROUND( (#value - FLOOR(#value)) / #roundamt, 0 ) * #roundamt + FLOOR(#value)
-- result = 1.750000
different rounding strategies like 0.02, 0.25, 0.5, 0.75
SELECT
x.roundamt, ROUND( (#value - FLOOR(#value)) / roundamt, 0 ) * roundamt + FLOOR(#value)
FROM
( VALUES (0.02), (0.25), (0.5), (0.75) )x(roundamt)
For anyone who need to find the closest divider without a remainder you can use:
SELECT (CAST(ROUND(#value / 0.25, 2) as int)) * 0.25
So basically this will round down to the closest multiple of 0.25

How can I create combinations of several lists without hardcoding loops?

I have data that looks like this:
my #homopol = (
["T","C","CC","G"], # part1
["T","TT","C","G","A"], #part2
["C","CCC","G"], #part3 ...upto part K=~50
);
my #prob = ([1.00,0.63,0.002,1.00,0.83],
[0.72,0.03,1.00, 0.85,1.00],
[1.00,0.97,0.02]);
# Note also that the dimension of #homopol is always exactly the same with #prob.
# Although number of elements can differ from 'part' to 'part'.
What I want to do is to
Generate all combinations of elements in part1 through out partK
Find the product of the corresponding elements in #prob.
Hence at the end we hope to get this output:
T-T-C 1 x 0.72 x 1 = 0.720
T-T-CCC 1 x 0.72 x 0.97 = 0.698
T-T-G 1 x 0.72 x 0.02 = 0.014
...
G-G-G 1 x 0.85 x 0.02 = 0.017
G-A-C 1 x 1 x 1 = 1.000
G-A-CCC 1 x 1 x 0.97 = 0.970
G-A-G 1 x 1 x 0.02 = 0.020
The problem is that the following code of mine does that by hardcoding
the loops. Since the number of parts of #homopol is can be varied and large
(e.g. ~K=50), we need a flexible and compact way to get the same result. Is there any?
I was thinking to use Algorithm::Loops, but not sure how to achieve that.
use strict;
use Data::Dumper;
use Carp;
my #homopol = (["T","C","CC","G"],
["T","TT","C","G","A"],
["C","CCC","G"]);
my #prob = ([1.00,0.63,0.002,1.00,0.83],
[0.72,0.03,1.00, 0.85,1.00],
[1.00,0.97,0.02]);
my $i_of_part1 = -1;
foreach my $base_part1 ( #{ $homopol[0] } ) {
$i_of_part1++;
my $probpart1 = $prob[0]->[$i_of_part1];
my $i_of_part2 =-1;
foreach my $base_part2 ( #{ $homopol[1] } ) {
$i_of_part2++;
my $probpart2 = $prob[1]->[$i_of_part2];
my $i_of_part3 = -1;
foreach my $base_part3 ( #{ $homopol[2] } ) {
$i_of_part3++;
my $probpart3 = $prob[2]->[$i_of_part3];
my $nstr = $base_part1."".$base_part2."".$base_part3;
my $prob_prod = sprintf("%.3f",$probpart1 * $probpart2 *$probpart3);
print "$base_part1-$base_part2-$base_part3 \t";
print "$probpart1 x $probpart2 x $probpart3 = $prob_prod\n";
}
}
}
I would recommend Set::CrossProduct, which will create an iterator to yield the cross product of all of your sets. Because it uses an iterator, it does not need to generate every combination in advance; rather, it yields each one on demand.
use strict;
use warnings;
use Set::CrossProduct;
my #homopol = (
[qw(T C CC G)],
[qw(T TT C G A)],
[qw(C CCC G)],
);
my #prob = (
[1.00,0.63,0.002,1.00],
[0.72,0.03,1.00, 0.85,1.00],
[1.00,0.97,0.02],
);
# Prepare by storing the data in a list of lists of pairs.
my #combined;
for my $i (0 .. $#homopol){
push #combined, [];
push #{$combined[-1]}, [$homopol[$i][$_], $prob[$i][$_]]
for 0 .. #{$homopol[$i]} - 1;
};
my $iterator = Set::CrossProduct->new([ #combined ]);
while( my $tuple = $iterator->get ){
my #h = map { $_->[0] } #$tuple;
my #p = map { $_->[1] } #$tuple;
my $product = 1;
$product *= $_ for #p;
print join('-', #h), ' ', join(' x ', #p), ' = ', $product, "\n";
}
A solution using Algorithm::Loops without changing the input data would look something like:
use Algorithm::Loops;
# Turns ([a, b, c], [d, e], ...) into ([0, 1, 2], [0, 1], ...)
my #lists_of_indices = map { [ 0 .. #$_ ] } #homopol;
NestedLoops( [ #lists_of_indices ], sub {
my #indices = #_;
my $prob_prod = 1; # Multiplicative identity
my #base_string;
my #prob_string;
for my $n (0 .. $#indices) {
push #base_string, $hompol[$n][ $indices[$n] ];
push #prob_string, sprintf("%.3f", $prob[$n][ $indices[$n] ]);
$prob_prod *= $prob[$n][ $indices[$n] ];
}
print join "-", #base_string; print "\t";
print join "x", #prob_string; print " = ";
printf "%.3f\n", $prob_prod;
});
But I think that you could actually make the code clearer by changing the structure to one more like
[
{ T => 1.00, C => 0.63, CC => 0.002, G => 0.83 },
{ T => 0.72, TT => 0.03, ... },
...
]
because without the parallel data structures you can simply iterate over the available base sequences, instead of iterating over indices and then looking up those indices in two different places.
Why don't you use recursion? Pass the depth as a parameter and let the function call itself with depth+1 inside the loop.
you could do it by creating an array of indicies the same length as the #homopol array (N say), to keep track of which combination you are looking at. In fact this array is just like a
number in base N, with the elements being the digits. Iterate in the same way as you would write down consectutive numbers in base N, e.g (0 0 0 ... 0), (0 0 0 ... 1), ...,(0 0 0 ... N-1), (0 0 0 ... 1 0), ....
Approach 1: Calculation from indices
Compute the product of lengths in homopol (length1 * length2 * ... * lengthN). Then, iterate i from zero to the product. Now, the indices you want are i % length1, (i / length1)%length2, (i / length1 / length2) % length3, ...
Approach 2: Recursion
I got beaten to it, see nikie's answer. :-)

Formatting Formulas by Code?

I have the following formula as the grouping for a Cross Tab Report:
{Command.Year} & ' ' & {Command.RF Period}
Year is a SmallInt and Period is a TinyInt.
The problem is that it shows on the report as:
2,009.00 9.00
The database values are actually:
2009 9
I can't remove the decimal places via formatting because they are in the formula together.
Ultimately I'd like it to be:
2009 09
Edit:
I found this link: http://www.kenhamady.com/form15.shtml
Now my code looks like this for period:
WhileReadingRecords;
StringVar text := Totext ( {Command.RF Period} , 6 , "" ) ; //put your numeric field in this line
NumberVar end := length ( text ) ;
NumberVar clip :=
(if Val ( text [ end - 6 to end ] ) = 0 then 1 else 0 ) +
(if Val ( text [ end - 5 to end ] ) = 0 then 1 else 0 ) +
(if Val ( text [ end - 4 to end ] ) = 0 then 1 else 0 ) +
(if Val ( text [ end - 3 to end ] ) = 0 then 1 else 0 ) +
(if Val ( text [ end - 2 to end ] ) = 0 then 1 else 0 ) +
(if Val ( text [ end - 1 to end ] ) = 0 then 1 else 0 ) +
(if Val ( text [ end - 0 to end ] ) = 0 then 1 else 0 ) ;
text [ 1 to Length ( text ) - clip ]
However, I don't use Crystal Language, I use VB. How do I append a 0 in front of the period if it does not begin with a 1?
The problem now is that September (9) shows up after October, Nov, and Dec because aphabetically 9 comes after 1.
Anybody?
The ToText function is very useful for this kind of thing, no loops required. In Crystal's VB Syntax :
Formula = ToText({Command.Year}, 0, "") & " " & ToText({Command.RF Period}, "00")
This should work if {Command.Year} and {Command.RF Period} are integers as you describe.