How do I prevent an int from becoming negative after subtracting - c#

I am trying to subtract a value from an int which has a set value. Once it gets to 0 and I subtract more from it, the value becomes negative.
I thought if I used an if-else statement to check whether the value goes below 0 it would prevent the value from becoming negative. But the value proceeds into the negative. How do I prevent the value from going into the negative range?
{
DateTime start = dateTimePicker2.Value.Date;
DateTime end = dateTimePicker1.Value.Date;
TimeSpan difference = end - start;
int days = difference.Days;
int min = 0;
int max = 21;
int rdays = Convert.ToInt32(Holidays_Number_lbl.Text);
Holidays_Number_lbl.Text = (rdays - days).ToString();
int Holidays_Number = int.Parse(Holidays_Number_lbl.Text);
if ((Holidays_Number > min) && (Holidays_Number < max))
{
MessageBox.Show("Holidays have been counted");
}
else
{
MessageBox.Show(" You have exceeded your 21 holidays ");//value goes into the minus ?
}
}
Expected result: MessageBox appears saying you have exceeded your days and value doesn't go into the negative.
Actual Result: Value proceeds into the negative.

You can specify zero as the lowest possible value with Math.Max()on the line where you do the arithmetic:
Holidays_Number_lbl.Text = (Math.Max(rdays - days, 0)).ToString();
However, you're converting to a string and then back to a number. Something like this would eliminate the need for int.Parse:
...
int Holidays_Number = Math.Max(rdays - days, 0);
Holidays_Number_lbl.Text = Holidays_Number.ToString();
if ((Holidays_Number > min) && (Holidays_Number < max))
{
...

This line int Holidays_Number = int.Parse(Holidays_Number_lbl.Text); is setting the value of Holidays_Number. Then the next line checks that with an if statement. But the if statement does not change the value, it just checks it. So if it is below 0, it will remain below 0.

Related

trying to find the biggest negative and smallest positive from given input

im trying to build an algorythm which input is 10 numbers (positive and negative) and the output is the smallest positive number and the biggest negative number.
im getting the right answer for the smallest positive, but not for the biggest negative.
code and output are inserted.
If you have a collection, say, int[] numbers you can just query it with a help of Linq:
using System.Linq;
...
int[] numbers = ...
...
// Either biggest negative or 0 (if we don't have any negative values)
int biggestNegative = numbers
.Where(x => x < 0)
.DefaultIfEmpty() // <- we don't want exception on empty input
.Max();
// Either smallest positive or 0 (if we don't have any positive values)
int smallestPositive = numbers
.Where(x => x > 0)
.DefaultIfEmpty() // <- we don't want exception on empty input
.Min();
If you prefer to compute the values in a for loop:
int biggestNegative = 0;
int smallestPositive = 0;
for (int i = 0; i < 10; ++i) {
...
// Simplest, you may want to check user input
int value = int.Parse(Console.ReadLine());
...
if (value > 0)
smallestPositive = smallestPositive == 0
? value
: Math.Min(smallestPositive, value);
else if (value < 0)
biggestNegative = biggestNegative == 0
? value
: Math.Max(biggestNegativee, value);
}
Let's print the values out:
Console.WriteLine(
$"Biggest negative: {(biggestNegative == 0 ? "???" : biggestNegative.ToString())}");
Console.WriteLine(
$"Smallest positive: {(smallestPositive == 0 ? "???" : smallestPositive.ToString())}");
if (num>negMax)
There is a mistake in this condition. As your initial negMax value is 0, no negative number will meet the condition, and therefore negMax value will never be updated.
You're initializing negMax as 0.
There is no negative number that is bigger than 0.
Depending on what exactly you want to accomplish, you could do one of the following:
Initialize negMax as int.MinValue
This would be okay if it's guaranteed that there's at least one negative number, since the first negative input is guaranteed to be equal or greater. If negative input isn't guaranteed, you cannot tell if there were any and your output may end up incorrect.
Modify the condition for assigning a new value to negMax
You could instead modify the condition for assigning a new value to negMax to if (num > negMax || negMax >= 0).
Since you usually don't treat 0 as a negative number (and if you do, you can initialize negMax with any positive number instead), you'd know that there were no negative numbers if the output ends up as 0.
To do the same with posMin, you'd have to initialize it as something less than 0 and adjust the if-condition for assigning a value to that variable accordingly.
Alternatively, you could also declare negMax and posMin as int?s and check for null instead of >= 0.
If you choose this way, you can check the values for both variables and output, for example, that no negative or no positive numbers were entered instead of outputting whichever placeholder you chose.

Can my conditional statement be based off of data types? [duplicate]

This question already has answers here:
C# testing to see if a string is an integer?
(10 answers)
Closed 8 years ago.
//capture input value for peak size and return
public static int GetPeakSize()
{
//declare variables, intitialize and parse after input
int peak;
Console.WriteLine("\nPlease enter the peak size (must be a number 1-10): ");
peak = int.Parse(Console.ReadLine());
//if user enter anything that is not inside the 1-10 range, default
//to 3
if (peak < 1 || peak > 10)
{
peak = 3;
}
return peak;
}
In the method above I'm just trying to gather input, parse it, and if the input does not fall in the range of 1-10, return a default value of 3. But instead of just validating numerical input, I want to return a default value of 3 if ANYTHING but the numerical values of 1-10 are entered. So if they enter "four" instead of 4, I'd like the value to default to 3. I wish I could do something along the lines of if (value != int || value < 1 || value > 10)......default = 3. I know this can't be done but is there anyway around it?
You might want to use TryParse instead:
int peak;
Console.WriteLine("\nPlease enter the peak size (must be a number 1-10): ");
if (!int.TryParse(Console.ReadLine(), out peak) || peak < 1 || peak > 10)
{
peak = 3;
}
The code above will attempt to parse the input into an int -- if it could not, or if the parsed value falls outside of your range constraints, it overrides peak to 3 before continuing on.
EDIT: Missed the range constraints.
Use int.TryParse. int.Parse will throw if the input is non-numeric.
int peak = 0;
bool parseSuccess = int.TryParse(input, out peak);
if (!parseSuccess || peak < 1 || peak > 10)
{
}
int.TryParse will return false if the input is not valid, and if it is valid, then the parsed value will be contained in the "out" parameter (peak in this case).

More efficient way to prevent a numeric string value from reducing its decimal precision

I have a a program that outputs a list of string values that it receives from a 3rd party application.
A request has been made that end users would like to see all the level of decimal precision to remain at the highest level it is set at. As each new value overwrites the last value there is no need to apply this backward, just forwards.
So if it goes to 3 levels of precision it should remain at that level afterwards.
Eg. if the values received were: 1, 15, 15.2, 4.25, 1.111, 3.4, 1 then the output would be:
1, 15, 15.2, 4.25, 1.111, 3.400, 1.000
I've written the following code which will do the job, but it doesn't seem very elegant to me. Performance is also very important here, as there could be 100s of samples coming up so this shouldn't effect performance. In fact if it's determined that this causes a noticeable slowdown of the application the the requirement will probably be dropped.
int numberOfDecimals = 0;
private string FormatValueToMinimumNumberOfDecimals(string value)
{
decimal doubleValue;
if (decimal.TryParse(value, out doubleValue))
{
int numberOfDecimals = this.CountDecimalPlace(doubleValue);
if (this.numberOfDecimals > numberOfDecimals)
{
value = doubleValue.ToString(String.Format("N{0}", this.numberOfDecimals.ToString()));
}
else
{
this.numberOfDecimals = numberOfDecimals;
}
}
return value;
}
private int CountDecimalPlace(decimal val)
{
int decimalCount = 0;
decimal ten = 10;
while (val != Math.Floor(val))
{
val *= ten;
decimalCount++;
}
return decimalCount;
}
So the question is can anyone think of a better/faster way of doing this?
Also if there are any obvious issues with the working solution provide, fell free to point them out.
To get the number of decimal places from a string use IndexOf:
var sep = NumberFormatInfo.CurrentInfo.CurrencyDecimalSeparator;
var pos = val.IndexOf(sep);
var pre = (pos == -1) ? 0 : val.Length - pos - 1;
To get the precision from a decimal type use Decimal.GetBits:
var pre = (Decimal.GetBits(val)[3] >> 16) & 0x000000FF;
Also, you can use NumberFormatInfo instead of String.Format().
NumberFormatInfo nfi = new NumberFormatInfo();
nfi.NumberDecimalDigits = this.numberOfDecimals;
value = doubleValue.ToString("N", nfi);

How to check if a Double can be converted into a Int32?

I have a double value that I'd like to convert into a Int32. How can I check before converting if it can be converted?
Sometimes the value is undefined and the Converting into Int32 throws an OverflowException.
I already tried to test it that way:
double value = getSomeValue();
if (value == Double.NAN) {
value =0;
}
int v = Convert.ToInt32(value);
But this does not cover all cases.
Maybe this?
Update: I believe the update below addresses the edge cases. I've tested this against every case I could think of verifying the output against a method that attempts Convert.ToInt32 directly and catches the exception.
static bool TryConvertToInt32(double value, out int result)
{
const double Min = int.MinValue - 0.5;
const double Max = int.MaxValue + 0.5;
// Notes:
// 1. double.IsNaN is needed for exclusion purposes because NaN compares
// false for <, >=, etc. for every value (including itself).
// 2. value < Min is correct because -2147483648.5 rounds to int.MinValue.
// 3. value >= Max is correct because 2147483648.5 rounds to int.MaxValue + 1.
if (double.IsNaN(value) || value < Min || value >= Max)
{
result = 0;
return false;
}
result = Convert.ToInt32(value);
return true;
}
Check whether Double.IsNaN and make sure it's between int.MinValue and int.MaxValue,
You could compare to the range of an Int32.
if(value <= (double)Int32.MAX_VALUE && value >= (double)Int32.MIN_VALUE)
return (Int32)value;
return 0;
Of course, if you want to return Max/Min value when the double is too large, you could do this:
if(value <= (double)Int32.MAX_VALUE && value >= (double)Int32.MIN_VALUE)
return (Int32)value;
if(value > (double)Int32.MAX_VALUE)
return Int32.MAX_VALUE;
if(value < (double)Int32.MIN_VALUE)
return Int32.MIN_VALUE;
return 0;
Try something like this:
double d = Double.NaN;
int i;
if(Int32.TryParse(d.ToString(), out i))
{
Console.WriteLine("Success");
Console.WriteLine(i);
} else {
Console.WriteLine("Fail");
}
Unless you absolutely need the performance, what about using exception handling?
You could try something like this:
(value>=Int32.MinValue)&&(value<=Int32.MaxValue)
This will probably falsely reject values which are outside the value range of int but get rounded into it. So you might want to extent the interval a bit.
For example Int32.MaxValue+0.1 gets rejected.
How do you want to treat non integral doubles? This code accepts them and silently rounds away the fractional part. The suggestions based on int.TryParse(value.ToString(),...) will throw consider such doubles invalid.

Dynamic number format in .NET?

I have a problem and cant find a solution. I have numbers (decimal) like 85.12343 or 100 or 1.123324. I want to format this in a way that the result is always 13 chars long including the separator.
100 --> 100.000000000
1.123324 --> 1.12332400000
I tried with toString, but failed. How could I do this?
Thanks :)
int digits = 13;
decimal d = 100433.2414242241214M;
int positive = Decimal.Truncate(d).ToString().Length;
int decimals = digits - positive - 1; //-1 for the dot
if (decimals < 0)
decimals = 0;
string dec = d.ToString("f" + decimals);
It will not remove digits from the whole part, only the fraction, when needed.
I'd go with Kobi's answer, unless it's possible you could have more than 13 digits to start with, in which case you might need to do something like this (warning: I have not even attempted to make this efficient; surely there are ways it could be optimized if necessary):
public static string ToTrimmedString(this decimal value, int numDigits)
{
// First figure out how many decimal places are to the left
// of the decimal point.
int digitsToLeft = 0;
// This should be safe since you said all inputs will be <= 100M anyway.
int temp = decimal.ToInt32(Math.Truncate(value));
while (temp > 0)
{
++digitsToLeft;
temp /= 10;
}
// Then simply display however many decimal places remain "available,"
// taking the value to the left of the decimal point and the decimal point
// itself into account. (If negative numbers are a possibility, you'd want
// to subtract another digit for negative values to allow for the '-' sign.)
return value.ToString("#." + new string('0', numDigits - digitsToLeft - 1));
}
Example inputs/output:
Input Output
---------------------------------------
100 100.000000000
1.232487 1.23248700000
1.3290435309439872321 1.32904353094
100.320148109932888473 100.320148110
0.000383849080819849081 .000383849081
0.0 .000000000000
Quick 'n' dirty:
return (value.ToString("0.#") + "0000000000000").Substring(0, 13);
string formatted = original.ToString("0.000000000000").Remove(13);
Besides simply padding the string you can do some more elaborate math to determine the number of digits:
String FormatField(Int32 fieldWidth, Decimal value) {
var integerPartDigits =
value != Decimal.Zero ? (int) Math.Log10((Double) value) + 1 : 1;
var fractionalPartDigits = Math.Max(0, fieldWidth - integerPartDigits - 1);
return value.ToString("F" + fractionalPartDigits);
}
Note that if the value is negative or has an integer part with one less digit than the field width you will not get the desired result. However, you can modify the code to accommodate these cases based on exactly how you want to format and align these numbers.
What about
string newString;
if (original.ToString().Length >= 13)
{
newString = original.ToString().Substring(13);
}
else
{
newString = original.ToString().PadRight(13, '0');
}
int noofdecimal=3;
double value=1567.9800
value.ToString("#." + new string('0', noofdecimal));
//Result=1567.980

Categories

Resources