IIF condition in SSRS and handling zeros - reporting-services

I've got a fairly complex formula in SSRS and for some reason it shows an error when it encounters a zero value, even though I'm handling zeros in my formula. Can anybody advise how to fix this issue?
=iif(datepart("h",Now())=6, iif(SUM(Fields!PYRevenue.Value) = 0, 0,((SUM(Fields!Revenue.Value) - SUM(Fields!PYRevenue.Value)) / SUM(Fields!PYRevenue.Value)))
,iif(SUM(Fields!PYRevenue.Value) = 0, 0,(SUM(Fields!Revenue.Value) / SUM(Fields!PYRevenue.Value))))

Sorry, I misread your formula until I indented it properly. Even though you have a check for PYRevenue = 0, you need to also include another IIF() after both occurrences of "/", like so:
iif(
SUM(Fields!PYRevenue.Value) = 0,
0,
(
(SUM(Fields!Revenue.Value) - SUM(Fields!PYRevenue.Value)
) / IIF(SUM(Fields!PYRevenue.Value) = 0, 1, SUM(Fields!PYRevenue.Value))
)
SSRS evaluates all the expressions so you have to handle the 0 value even if your parent logic prevents that block from being hit.

Apologies for the hurried answer... Doing this on my phone..
Even though your last expression will not be used if SUM(PYRevenue) is zero, it will still get evaluated and give a divide by zero error.
2 ways to resolve.
I personally use SWITCH instead of IIF for anything that is not simple.
Alternatively you need to check SUM(PYRevenue) on both side of your division. Pseudo code would be =IIF(SUM(PYRevenue)=0,0,SUM(Revenue)) / IIF(SUM(PYRevenue)=0, 1, SUM(PYRevenue)) So if sum PY is zero then do 0/1 else do revenue/pyrevenue

Related

SSRS 2012 Custom Code/Expression for Divide by Zero and calculations

I know similar questions have been asked. However, I have not found anything that exactly helps me out in my situation.
I need to avoid divide by zero but before I do a divide with another column value, I am performing a math calculation:
=Sum((Fields!col1.Value) - Sum(Fields!col2.Value) / Sum(Fields!col2.Value))
I basically want to do a subtraction first, then a divide but I am unable to get the expression or the custom code to work for me. And before I spend too many hours on this one, I figured I would reach out for help.
This is the code I have come up with so far and it works, but I want the column to show nothing instead of 0:
=IIf(Sum(Fields!LWCasesBudget.Value) = 0, 0,
Sum(Fields!LWShipQuantity.Value) - Sum(Fields!LWCasesBudget.Value))/
IIf(Sum(Fields!LWCasesBudget.Value) = 0, 1, Sum(Fields!LWCasesBudget.Value))
It seems like you are happy with your calculation. If the 0 is the only issue then try and replace the 0 with the word "nothing".
Example:
=IIf(Sum(Fields!LWCasesBudget.Value) = 0, nothing,
Sum(Fields!LWShipQuantity.Value) - Sum(Fields!LWCasesBudget.Value))/
IIf(Sum(Fields!LWCasesBudget.Value) = 0, 1, Sum(Fields!LWCasesBudget.Value))
Hope that helps.

Is it impossible to increment in a for loop by decimal numbers in actionScript 3 and get accurate results?

I can't seem to find an answer for this anywhere online, but this for loop, although seemingly valid, creates an infinite loop because actionscript does not seem to recognize 0.1, 0.2, 0.3, and so on. This for loop will just trace 0, 0, 0, and so on infinitely.
Can anyone tell me why actionscript does this, and is there a way to get to precise decimal number increments in actionscript?
for(var i:int = 0; i<1; i = i + 0.1)
{
trace(i);
}
The initial problem, as reported in Hobo Sapiens's comment, is that you have declared i as int, but want it to store fractions. However, even after you have fixed that, you are likely to encounter rounding error issues. Adding up a floating point approximation to 0.1 is not a good way of getting the closest possible approximation to 0.9, or the exact value of 1.0.
There are generally two solutions:
Use a decimal data type. I have not been able to find a decimal arithmetic package for Actionscript, but that does not mean there isn't one.
Use an integer that represents a scaled version of the value you want. In the case of your loop, you would increment i by one on each iteration, and limit it to less than ten. You would then use a Number conversion of i, divided by ten, inside the loop. That results in using the closest floating point number to 0, 0.1, 0.2 etc. inside the loop.
Can't comment yet, so I'll post it as an answer:
There are definitely cases where increments by a float value are useful. And if it was absolutely wrong, why would it then be possible at all?
What akmozo suggested is a good way to do it, instead of doing the increment i = i + 0.1 you can do i = Number((i+0.1).toFixed(decimalSpacesYouWant)). This will return a number without the usual rounding problems. It gets especially useful with very small values (converging towards zero) which tend to flip into Infinity or NaN at some point.

Why is a field with a value of 0 not the same as 0 in this formula? [duplicate]

This question already has answers here:
Inconsistency in divide-by-zero behavior between different value types
(5 answers)
Closed 8 years ago.
We've got a report calculating margin which is pretty simple. I understand that there is no short circuiting of an IIF in SSRS. This question is focused on why there is a behavior difference between using field values in a formula, and direct values.
=IIF(SUM(Fields!Sales.Value) = 0, "N/A", 1 - SUM(Fields!Cost.Value) / SUM(Fields!Sales.Value))
This formula results in #error when Sales.Value = 0. However, if I change the formula to the following:
=IIF(SUM(Fields!Sales.Value) = 0, "N/A", 1 - 1 / 0)
This results in "N/A" like it's supposed to. So 1 - / 0 = -infinity, but dividing by a field whose value is 0 results in an error.
Why is the behavior different here?
EDIT: I'll clarify this a bit. Ignoring the IIF aspect of this, if I do:
= 1 - 1 / 0
I get -infinity. If I do (where Sales.Value = 0):
= 1 -1 / Fields!Sales.Value
I get #error.
Based on VB documentation, the Double data type is the only data type that does not throw the DivideByZeroException. But since you've clearly used two Int's, something else is going on here.
After some searching I found this answer to a related but different divide-by-zero question, which has a great explanation:
VB.NET does things a little bit differently; integer division automatically results in a floating point value using the / operator. This is to allow developers to write, e.g., the expression 1 / 2, and have it evaluate to 0.5, which some would consider intuitive
TL;DR Fields!Sales.Value is likely interpreted as a Decimal resulting in the divide-by-zero #error, while the 1 / 0 example results in a data type of Double and displays infinity.

NaN and Infinity values in SSRS

I am using Visual Studio to build my report and I have tried to use those three expressions:
=IIF(Fields!A.Value = 0 or Fields!B.Value = 0, 0,SUM(Fields!A.Value)/SUM(Fields!A.Value)
=IIF(SUM(Fields!A.Value) = 0 or SUM(Fields!B.Value =0),0,SUM(Fields!A.Value)/SUM(Fields!A.Value)
=Replace(Round((((SUM(Fields!A.Value)/SUM(Fields!B.Value)))*100),0),"NaN","0")+"%"
The first 2 give me only 0 as % and the last one doesnt get rid of Infinity but does get rid of NaN.
Can someone please help where I can use both these expressions together and not get only 0% and Infinity when I use either the top 2 or the last one?
At first, you need to be sure that the fields you are using to calculate your value are really numbers.
Normally, you get NaN when trying to divide 0 / 0 or Infinity when you are dividing any number by 0.
So, a generic resolution for NaN, Infinity or even #Error (that happens when a null value is passed to a division) is to create a Function that will work on this values for you.
Right click on the background of your report and go to Report Properties as shown:
Then you can go on tab Code and add your custom code:
Public Function Divide(ByVal dividend As Double, ByVal divisor As Double) As Double
If IsNothing(divisor) Or divisor = 0 Or IsNothing(dividend) Or dividend = 0 Then
Return 0
Else
Return dividend / divisor
End If
End Function
We use IsNothing() to avoid #Error and check whether the divisor or the dividend are 0 to avoid NaN and Infinity.
And then you replace your expression with:
= Code.Divide(Sum(Fields!A.Value), Sum(Fields!B.Value))
To make this looks like a percentage, I strongly recommend you change your Textbox properties. So, right click on it, go on Textbox Properties and over tab Number. Select category Percentage.
By doing this, you make sure that de SSRS will consider this value as percentage and not a text even when it is exported to other platforms such as Excel.
You can also check the Microsoft documentation on adding code to a Report (SSRS)
If you're getting 0% and NaN I'd check check your field data types. You should have at least one non-integer, and both need to be numeric. I'd still expect to see some 1s, but this is a start at the 0% and NaN. In terms of your check, you only need to check the denominator to avoid a calculation error.
Try:
=IIF(Sum(Fields!B.Value) <> 0 , Sum(Fields!A.Value) / Sum(Fields!B.Value), 0 )
Control your presentation (decimal places, % sign etc.) with the textbox Format properties, or the equation number properties.

Compute real roots of a quadratic equation in Pascal

I am trying to solve this problem :
(Write a program to compute the real roots of a quadratic equation (ax2 + bx + c = 0). The roots can be calculated using the following formulae:
x1 = (-b + sqrt(b2 - 4ac))/2a
and
x2 = (-b - sqrt(b2 - 4ac))/2a
I wrote the following code, but its not correct:
program week7_lab2_a1;
var a,b,c,i:integer;
x,x1,x2:real;
begin
write('Enter the value of a :');
readln(a);
write('Enter the value of b :');
readln(b);
write('Enter the value of c :');
readln(c);
if (sqr(b)-4*a*c)>=0 then
begin
if ((a>0) and (b>0)) then
begin
x1:=(-1*b+sqrt(sqr(b)-4*a*c))/2*a;
x2:=(-1*b-sqrt(sqr(b)-4*a*c))/2*a;
writeln('x1=',x1:0:2);
writeln('x2=',x2:0:2);
end
else
if ((a=0) and (b=0)) then
write('The is no solution')
else
if ((a=0) and (b<>0)) then
begin
x:=-1*c/b;
write('The only root :',x:0:2);
end;
end
else
if (sqr(b)-4*a*c)<0 then
write('The is no real root');
readln;
end.
do you know why?
and taking a=-6,b=7,c=8 .. can you desk-check it after writing the pesudocode?
You have an operator precedence error here:
x1:=(-1*b+sqrt(sqr(b)-4*a*c))/2*a;
x2:=(-1*b-sqrt(sqr(b)-4*a*c))/2*a;
See at the end, the 2 * a doesn't do what you think it does. It does divide the expression by 2, but then multiplies it by a, because of precedence rules. This is what you want:
x1:=(-1*b+sqrt(sqr(b)-4*a*c))/(2*a);
x2:=(-1*b-sqrt(sqr(b)-4*a*c))/(2*a);
In fact, this is because the expression is evaluated left-to-right wrt brackets and that multiplication and division have the same priority. So basically, once it's divided by 2, it says "I'm done with division, I will multiply what I have now with a as told".
As it doesn't really seem clear from the formula you were given, this is the quadratic formula:
As you can see you need to divide by 2a, so you must use brackets here to make it work properly, just as the correct text-only expression for this equation is x = (-b +- sqrt(b^2 - 4ac)) / (2a).
Otherwise the code looks fine, if somewhat convoluted (for instance, you could discard cases where (a = 0) and (b = 0) right after input, which would simplify the logic a bit later on). Did you really mean to exclude negative coefficients though, or just zero coefficients? You should check that.
Also be careful with floating-point equality comparison - it works fine with 0, but will usually not work with most constants, so use an epsilon instead if you need to check if one value is equal to another (like such: abs(a - b) < 1e-6)
Completely agree with what Thomas said in his answer. Just want to add some optimization marks:
You check the discriminant value in if-statement, and then use it again:
if (sqr(b)-4*a*c)>=0 then
...
x1:=(-1*b+sqrt(sqr(b)-4*a*c))/2*a;
x2:=(-1*b-sqrt(sqr(b)-4*a*c))/2*a;
This not quite efficient - instead of evaluating discriminant value at once you compute it multiple times. You should first compute discriminant value and store it into some variable:
D := sqr(b)-4*a*c;
and after that you can use your evaluated value in all expressions, like this:
if (D >= 0) then
...
x1:=(-b+sqrt(D)/(2*a);
x2:=(-b-sqrt(D)/(2*a);
and so on.
Also, I wouldn't write -1*b... Instead of this just use -b or 0-b in worst case, but not multiplication. Multiplication here is not needed.
EDIT:
One more note:
Your code:
if (sqr(b)-4*a*c)>=0 then
begin
...
end
else
if (sqr(b)-4*a*c)<0 then
write('The is no real root');
You here double check the if-condition. I simplify this:
if (a) then
begin ... end
else
if (not a)
...
Where you check for not a (in your code it corresponds to (sqr(b)-4*a*c)<0) - in this case condition can be only false (for a) and there is no need to double check it. You should just throw it out.