Protecting against Divide by Zero - c#

I'm running into a problem that I think in my mind should work, but keep returning the same Divide by Zero error.
Here is the code I am using that I think should protect against it:
GoalBarValue = Convert.ToInt32(((decimal)CompletedToday /
((decimal)CompletedYesterday) == 0 ? (decimal?)null : (decimal)CompletedYesterday)
* 100); // Divide by zero protection
CompletedToday comes back as 0
CompletedYesterday comes back as 0
Which is perfectly fine and as I expect it should.
The specific error that is being returned is Attempted to divide by zero.
Is something wrong with the way I am trying to protect against it?

"Is something wrong with the way I am trying to protect against it?"
Yes actually, you are dividing by zero! The only way that 0 can be the outcome of your calculation is when CompletedToday is 0. In the other case you divide by 0 and get the nice exception. Why don't you just check whether the divisor is 0 and if not perform the calculation else give it a null :
GoalBarValue = Convert.ToInt32((decimal)CompletedYesterday) == 0 ?
(decimal?)null : (decimal)CompletedYesterday * 100;
Imagine you would check whether you hit your head against a wall by hitting your head against the wall..... it wouldn't be advisable.
EDIT:
If you want 2 assignments of different variables (as you wrote in your comment) then the ? operator is not of much use to you. It allows only 1.
I would suggest to stick to the old fashion way. If you really want the 2 assignments in one line:
if((decimal)CompletedYesterday) == 0)
GoalBarValue = CompletedYesterday = null;
else GoalBarValue = // what ever you want to calculate...

Is this what you want?
if (Convert.ToDecimal(CompletedYesterday) == 0)
{
goalBarValue = null;
}
else
{
goalBarValue = Convert.ToInt32(Convert.ToDecimal(CompletedToday)/Convert.ToDecimal(CompletedYesterday)) * 100;
}
one line version of above code
goalBarValue = Convert.ToDecimal(CompletedYesterday) == 0 ? null : Convert.ToInt32(Convert.ToDecimal(CompletedToday)/Convert.ToDecimal(CompletedYesterday)) * 100;

Related

Test a subtraction and apply it if the result is greater than zero

I'm minimalist and I want that my code has as less lines as possible. In every code I write, my goal is to use as much one-lined instructions as possible and avoiding any recurrent code.
Today I'm facing a problem, I'm not able to reduce an instruction even if I'm convinced it's possible.Let's have a look at my instruction :
if((level - 2) >= 0)
{
level -= 2;
}
If know I can use a one-lined affectation in the if like that :
if((level -= 2) >= 0)
But the subtraction while be always applied even if the test is false.
How can I compact this instruction in one line ?
EDIT
I can't use ternary operator because I have to keep the if instruction. Basically I have to execute several operations if the test is true, I just simplified my code to post it.
You could use the ternary operator like this
level -= level - 2 >= 0 ? 2 : 0;
or simpler
level -= level >= 2 ? 2 : 0;
But I don't think that making everything as "short " as possible is the right way to go.
Only subtract when the level is larger or equal to the value you would subtract.
if(level >= 2)
{
level -= 2;
}
Write a general function:
public static bool TryToSubtract(ref int from, int value)
{
bool result = false;
if (from >= value)
{
from -= value;
result = true;
}
return result;
}
and then use that
TryToSubtract(ref level, 2);
You can then even make further statements based on the outcome:
if(TryToSubtract(ref level, 2))
{
Console.WriteLine("Your level was reduced!");
Console.WriteLine("You loser!");
}
If you can live without curlies and newlines, then this could be the shortest, and still very readable (IMHO):
if (level >= 2) level -= 2;

C# getting first digit of int in custom class

I am trying to build a help function in my guess the number game, whereby the user gets the first digit of the number he/she has to guess. So if the generated number is 550, he will get the 5.
I have tried a lot of things, maybe one of you has an idea what is wrong?
public partial class Class3
{
public Class3()
{
double test = Convert.ToDouble(globalVariableNumber.number);
while (test > 10)
{
double firstDigit = test / 10;
test = Math.Round(test);
globalVariableNumber.helpMe = Convert.ToString(firstDigit);
}
}
}
Under the helpButton clicked I have:
private void helpButton_Click(object sender, EventArgs e)
{
label3.Text = globalVariableNumber.helpMe;
label3.AutoSize = true;
That is my latest try, I putted all of this in a custom class. In the main I putted the code to show what is in the helpMe string.
If you need more code please tell me
Why not ToString the number and use Substring to get the first character?
var number = 550;
var result = number.ToString().Substring(0, 1);
If for some reason you dont want to use string manipulation you could do this mathematically like this
var number = 550;
var result = Math.Floor(number / Math.Pow(10, Math.Floor(Math.Log10(number))));
What's wrong - you have an infinite while loop there. Math.Round(test) will leave the value of test unchanged after the first iteration.
You may have intended to use firstDigit as the variable controlling the loop.
Anyway, as suggested by others, you can set helpMe to the first digit by converting to a string and using the first character.
As an aside, you should consider supplying the number as a parameter and returning the helpMe string from the method. Your current approach is a little brittle.
The problem with your code is that you are doing the division and storing that in a separate variable, then you round the original value. That means that the original value only changes in the first iteration of the loop (and is only rounded, not divided), and unless that happens to make the loop condition false (i.e. for values between 10 and 10.5), the loop will never end.
Changes:
Use an int intead of a double, that gets you away from a whole bunch of potential precision problems.
Use the >= operator rather than >. If you get the value 10 then you want the loop to go on for another iteration to get a single digit.
You would use Math.Floor instead of Math.Round as you don't want the first digit to be rounded up, i.e. getting the first digit for 460 as 5. However, if you are using an integer then the division truncates the result, so there is no need to do any rounding at all.
Divide the value and store it back into the same variable.
Use the value after the loop, there is no point in updating it while you still have multiple digits in the variable.
Code:
int test = (int)globalVariableNumber.number;
while (test >= 10) {
test = test / 10;
}
globalVariableNumber.helpMe = test.ToString();
By using Math.Round(), in your example, you're rounding 5.5 to 6 (it's the even integer per the documentation). Use Math.Floor instead, this will drop the decimal point but give you the number you're expecting for this test.
i.e.
double test = Convert.ToDouble(globalVariableNumber.number);
while (test > 10)
{
test = Math.Floor(test / 10);
globalVariableNumber.helpMe = Convert.ToString(firstDigit);
}
Like #Sam Greenhalgh mentions, though, returning the first character of the number as a string will be cleaner, quicker and easier.
globalVariableNumber.helpMe = test >= 10
? test.ToString().SubString(0, 1)
: "Hint not possible, number is less than ten"
This assumes that helpMe is a string.
Per our discussion in the comments, you'd be better off doing it like this:
private void helpButton_Click(object sender, EventArgs e)
{
label3.Text = GetHelpText();
label3.AutoSize = true;
}
// Always good practice to name a method that returns something Get...
// Also good practice to give it a descriptive name.
private string GetHelpText()
{
return test >= 10 // The ?: operator just means if the first part is true...
? test.ToString().SubString(0, 1) // use this, otherwise...
: "Hint not possible, number is less than ten" // use this.
}

Terras Conjecture in C#

I'm having a problem generating the Terras number sequence.
Here is my unsuccessful attempt:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Terras
{
class Program
{
public static int Terras(int n)
{
if (n <= 1)
{
int return_value = 1;
Console.WriteLine("Terras generated : " + return_value);
return return_value;
}
else
{
if ((n % 2) == 0)
{
// Even number
int return_value = 1 / 2 * Terras(n - 1);
Console.WriteLine("Terras generated : " + return_value);
return return_value;
}
else
{
// Odd number
int return_value = 1 / 2 * (3 * Terras(n - 1) + 1);
Console.WriteLine("Terras generated : " + return_value);
return return_value;
}
}
}
static void Main(string[] args)
{
Console.WriteLine("TERRAS1");
Terras(1); // should generate 1
Console.WriteLine("TERRAS2");
Terras(2); // should generate 2 1 ... instead of 1 and 0
Console.WriteLine("TERRAS5");
Terras(5); // should generate 5,8,4,2,1 not 1 0 0 0 0
Console.Read();
}
}
}
What am I doing wrong?
I know the basics of recursion, but I don’t understand why this doesn’t work.
I observe that the first number of the sequence is actually the number that you pass in, and subsequent numbers are zero.
Change 1 / 2 * Terros(n - 1); to Terros(n - 1)/2;
Also 1 / 2 * (3 * Terros(n - 1) + 1); to (3 * Terros(n - 1) + 1)/2;
1/2 * ... is simply 0 * ... with int math.
[Edit]
Recursion is wrong and formula is mis-guided. Simple iterate
public static void Terros(int n) {
Console.Write("Terros generated :");
int t = n;
Console.Write(" " + t);
while (t > 1) {
int t_previous = t;
if (t_previous%2 == 0) {
t = t_previous/2;
}
else {
t = (3*t_previous+1)/2;
}
Console.Write(", " + t);
}
Console.WriteLine("");
}
The "n is even" should be "t(subscript n-1) is even" - same for "n is odd".
int return_value = 1 / 2 * Terros(n - 1);
int return_value = 1 / 2 * (3 * Terros(n - 1) + 1);
Unfortunately you've hit a common mistake people make with ints.
(int)1 / (int)2 will always be 0.
Since 1/2 is an integer divison it's always 0; in order to correct the math, just
swap the terms: not 1/2*n but n/2; instead of 1/2* (3 * n + 1) put (3 * n + 1) / 2.
Another issue: do not put computation (Terros) and output (Console.WriteLine) in the
same function
public static String TerrosSequence(int n) {
StringBuilder Sb = new StringBuilder();
// Again: dynamic programming is far better here than recursion
while (n > 1) {
if (Sb.Length > 0)
Sb.Append(",");
Sb.Append(n);
n = (n % 2 == 0) ? n / 2 : (3 * n + 1) / 2;
}
if (Sb.Length > 0)
Sb.Append(",");
Sb.Append(n);
return Sb.ToString();
}
// Output: "Terros generated : 5,8,4,2,1"
Console.WriteLine("Terros generated : " + TerrosSequence(5));
The existing answers guide you in the correct direction, but there is no ultimate one. I thought that summing up and adding detail would help you and future visitors.
The problem name
The original name of this question was “Conjuncture of Terros”. First, it is conjecture, second, the modification to the original Collatz sequence you used comes from Riho Terras* (not Terros!) who proved the Terras Theorem saying that for almost all t₀ holds that ∃n ∈ ℕ: tₙ < t₀. You can read more about it on MathWorld and chux’s question on Math.SE.
* While searching for who is that R. Terras mentioned on MathWorld, I found not only the record on Geni.com, but also probable author of that record, his niece Astrid Terras, and her family’s genealogy. Just for the really curious ones. ☺
The formula
You got the formula wrong in your question. As the table of sequences for different t₀ shows, you should be testing for parity of tₙ₋₁ instead of n.
Formula taken from MathWorld.
Also the second table column heading is wrong, it should read t₀, t₁, t₂, … as t₀ is listed too.
You repeat the mistake with testing n instead of tₙ₋₁ in your code, too. If output of your program is precisely specified (e.g. when checked by an automatic judge), think once more whether you should output t₀ or not.
Integer vs float arithmetic
When making an operation with two integers, you get an integer. If a float is involved, the result is float. In both branches of your condition, you compute an expression of this form:
1 / 2 * …
1 and 2 are integers, therefore the division is integer division. Integer division always rounds down, so the expression is in fact
0 * …
which is (almost*) always zero. Mystery solved. But how to fix it?
Instead of multiplying by one half, you can divide by two. In even branch, division by 2 gives no remainder. In odd branch, tₙ₋₁ is odd, so 3 · tₙ₋₁ is odd too. Odd plus 1 is even, so division by two always produces remainder equal to zero in both branches. Integer division is enough, the result is precise.
Also, you could use float division, just replace 1 with 1.0. But this will probably not give correct results. You see, all members of the sequence are integers and you’re getting float results! So rounding with Math.Round() and casting to integer? Nah… If you can, always evade using floats. There are very few use cases for them, I think, most having something to do with graphics or numerical algorithms. Most of the time you don’t really need them and they just introduce round-off errors.
* Zero times whatever could produce NaN too, but let’s ignore the possibility of “whatever” being from special float values. I’m just pedantic.
Recursive solution
Apart from the problems mentioned above, your whole recursive approach is flawed. Obviously you intended Terras(n) to be tₙ. That’s not utterly bad. But then you forgot that you supply t₀ and search for n instead of the other way round.
To fix your approach, you would need to set up a “global” variable int t0 that would be set to given t₀ and returned from Terras(0). Then Terras(n) would really return tₙ. But you wouldn’t still know the value of n when the sequence stops. You could only repeat for bigger and bigger n, ruining time complexity.
Wait. What about caching the results of intermediate Terras() calls in an ArrayList<int> t? t[i] will contain result for Terras(i) or zero if not initialized. At the top of Terras() you would add if (n < t.Count() && t[n] != 0) return t[n]; for returning the value immediately if cached and not repeating the computation. Otherwise the computation is really made and just before returning, the result is cached:
if (n < t.Count()) {
t[n] = return_value;
} else {
for (int i = t.Count(); i < n; i++) {
t.Add(0);
}
t.Add(return_value);
}
Still not good enough. Time complexity saved, but having the ArrayList increases space complexity. Try tracing (preferably manually, pencil & paper) the computation for t0 = 3; t.Add(t0);. You don’t know the final n beforehand, so you must go from 1 up, till Terras(n) returns 1.
Noticed anything? First, each time you increment n and make a new Terras() call, you add the computed value at the end of cache (t). Second, you’re always looking just one item back. You’re computing the whole sequence from the bottom up and you don’t need that big stupid ArrayList but always just its last item!
Iterative solution
OK, let’s forget that complicated recursive solution trying to follow the top-down definition and move to the bottom-up approach that popped up from gradual improvement of the original solution. Recursion is not needed anymore, it just clutters the whole thing and slows it down.
End of sequence is still found by incrementing n and computing tₙ, halting when tₙ = 1. Variable t stores tₙ, t_previous stores previous tₙ (now tₙ₋₁). The rest should be obvious.
public static void Terras(int t) {
Console.Write("Terras generated:");
Console.Write(" " + t);
while (t > 1) {
int t_previous = t;
if (t_previous % 2 == 0) {
t = t_previous / 2;
} else {
t = (3 * t_previous + 1) / 2;
}
Console.Write(", " + t);
}
Console.WriteLine("");
}
Variable names taken from chux’s answer, just for the sake of comparability.
This can be deemed a primitive instance of dynamic-programming technique. The evolution of this solution is common to the whole class of such problems. Slow recursion, call result caching, dynamic “bottom-up” approach. When you are more experienced with dynamic programming, you’ll start seeing it directly even in more complicated problems, not even thinking about recursion.

If Condition not Working ASp.Net?

i am trying to check condition before entering into it but it is entering in wrong condition
my conditions are ,
if (Target.Tables[0].Rows[0]["T_B_CX"].ToString() == "0" && Convert.ToInt64(Target.Tables[0].Rows[0]["T_B_C"]) >= 100000)
if (Target.Tables[0].Rows[0]["T_B_CX"].ToString() != "0" && Convert.ToInt64(Target.Tables[0].Rows[0]["T_B_C"]) > 10000000)
the values are,
T_B_CX = 0 and T_B_C = 2500000000
it must enter the fist condition i mentioned but it is entering in second condition???
Hopes for your suggestion thanks in advance
you can convert to int and do the comparison as below
if (Convert.ToInt(Target.Tables[0].Rows[0]["T_B_CX"].ToString()) == 0 && Convert.ToInt64(Target.Tables[0].Rows[0]["T_B_C"]) >= 100000)
may be when we get ToString of cell value it returns not exactly string equal to "0", debug and see which value you get for Target.Tables[0].Rows[0]["T_B_CX"].ToString()
There is no code between the two conditions, so the first one is taken as expected, then the second one is evaluated till the != 0.
Try to write something like this
// Convert everything just one time here
int tbcx = Convert.ToInt32(Target.Tables[0].Rows[0]["T_B_CX"]);
long tbc = Convert.ToInt64(Target.Tables[0].Rows[0]["T_B_C"]);
if(tbcx == 0 && tbc >= 100000)
// code here
else if(tbcx != 0 && tbc > 2500000000)
// code here
Also try to avoid the conversion of an integer value to a string and then check against a string.
It makes no sense. If an integer is stored in that table then convert it to an integer and check against an integer.

Checking bit state of lpt port binary

I've part of code which is checking input pins of lpt port, but using decimal values:
while (PortAccess.Input(889) == 120)
How to use this instruction with binary values?
for example while bit 3 of 00100100 is 0 then do something.
See Convert.ToInt32(string value, int fromBase)
while((value & Convert.ToInt32("00000100", 2)) == 0)
Or since we know the third bit is for (2^2)
while((value & 0x0004) == 0)
is also a clear enough piece of code, I guess.
Ok, so i've done this, because tafa solution wasn't working and i couldn't make it work:
var PortValue = Convert.ToString(PortAccess.Input(889), 2).PadLeft(8, '0');
PortV.Text = PortValue;
while (PortV.Text[3].ToString() == "1")
{
//some code
}
It's probably not good solution, but it's working ;)

Categories

Resources