How to make a method taking unknown amount of values? - c#

To explain the question on a simple example, let's say:
I have a method which takes the average of two numbers:
private double TakeAverage(double n1,double n2)
{
average = (number1 + number2) / 2.0000;
return average;
}
And I call it like:
textBox3.Text = (TakeAverage(number1, number2)).ToString();
Q1:
How to make this function able to run without calling it multiple times like:
TakeAverage(number1, number2, number3, number4, number5) // as wanted number of times...
Q2:how to make this function changing return value by number of values which it takes?
For example
Substring(1) //if it takes just one value, it returns all the chars after first char but
Substring(1,2)//if it takes two values, it returns 2 characters after first char

Check this out:
public double TakeAverage(params double[] numbers)
{
double result = 0.0;
if (numbers != null && numbers.Length > 0)
result = numbers.Average();
return result;
}
As params allows the client to send nothing, we should test whether numbers exists and has items.
Usage:
double average = TakeAverage(1, 2, 3, 4.4); //2.6
double anotherAverage = TakeAverage(); //0
double yetAnotherAverage = TakeAverage(null); //0
UPDATE
Based on your comments, I understand that you're looking for something that's called overload: you want that a given method behaves differently based on its arguments.
I'll give an example, you must modify it to suit your needs.
Let's pretend that, besides our original TakeAverage method, we want another one that does an average and multiplies it for a given number. It would be something like:
public double TakeAverage(int factor, params double[] numbers)
{
double result = 0.0;
if (numbers != null && numbers.Length > 0)
result = numbers.Average() * factor;
return result;
}
Usage:
double average = TakeAverage(1.0, 2, 3, 4.4); //2.6
double notAnAverage = TakeAverage(1, 2, 3, 4.4); //3.1333...
Note that I had to explicitly say that the first number is a double (1.0), otherwise it would fall on the second overload and multiply it.

There is the params-keyword where you can say that you take a not-specified amount of arguments.
From MSDN
The params keyword lets you specify a method parameter that takes a variable number of arguments.
You can send a comma-separated list of arguments of the type specified in the parameter declaration, or an array of arguments of the specified type. You also can send no arguments.
No additional parameters are permitted after the params keyword in a method declaration, and only one params keyword is permitted in a method declaration.
Example:
private double TakeAverage(params double[] numbers)
{
double average = 0.0;
if(numbers != null && numbers.Length > 0){
foreach(double d in numbers)
average += d;
average /= numbers.Length;
}
return average;
}

In response to your substring function question.
If you specify one argument, sub string(5) for example, it will return all the characters AFTER the 5th character in the string.
if I have the string "elephant", it would return "ant".
If I add a second argument to the function, it will start at the first given argument, as above, and go on x amount of characters before stopping.
if we use the above example string, "elephant" and do sub string(5,1) it would return "a".
(a good way to work this out is to add both numbers, that will be the last character in your string!)
What I'm asking it to do is create a new string going from the 5th character in the given string, and for my new string to be 1 character long.
This is because the string class has overloaded the sub-string method.
See here : http://msdn.microsoft.com/en-us/library/system.string.substring(v=vs.71).aspx

Related

A program that determines if the user feed is integer of decimal

I'm doing a school assignment in which we are assigned to make a program that asks the user to input a number. It then changes the input into a number and determines if the number is an integer or a decimal. If not possible, it says this to the user. The program cannot have errors that the users input can cause.
My problem is the part where the program determines if the feed is an integer or a decimal, if I input an integer, it says the number is integer and decimal, if I input a decimal, it ends in an error. The program never reaches catch (Exception) if the input is wrong.
public static void ITellYouYourNumbers(float number)
{
try
{
float d = number;
int isInt = (int)d;
Console.WriteLine("The number is a integer");
float isFloat = (float)d;
Console.WriteLine("The number is a decimal");
}
catch (Exception)
{
Console.WriteLine("Your input cannot be changed into a number. Try again.");
Console.ReadLine();
throw;
}
}
static void Main(string[] args)
{
Console.WriteLine("Write a number");
float num = float.Parse(Console.ReadLine());
ITellYouYourNumbers(num);
}
I've tried determening the d in different ways, such as:
decimal d = number
Console.WriteLine((d % 1) == 0);
d = number
Console.WriteLine((d % 1) == 0);
and
(d % 1) < epsilon
but nothing I've tried works. If the input is integer, it shows as an integer and decimal, if I input a decimal, it says that an error occured in the float num = float.Parse(Console.ReadLine()); , but it doesn't show up as an error in the program itself.
First, float.Parse() will fail with an exception if the string you put in can not be parsed as a float (beware of the high and low limits too, there are minimum and maximum values) and the exception will not be stopped by the catch since it was not generated in the try-catch block.
Second, a float can always be casted to an int.
Third, you are casting d to a float while d is already a float so why would it not work ?
Fourth, you are putting your float parameter (called "number") in another float inside the function (called "d"). While not wrong technically speaking, it bothers me to duplicate a value when you have no plan to modify either instance of it.
If you can modify the main, call directly your ITellYouYourNumbers function and put the string in without trying to parse it. If I understand the instructions of your exercise correctly, all you have to do is check that
1/ The string is not empty even after removing all blank characters at both ends.
2/ After trimming, it contains only numbers and at most one '.' or ',' character.
3/ If it contains a '.' or ',', it is a decimal. Otherwise, it is an integer.
If you are actually supposed to cast the input as a number, you can check if it represents an integer by exploiting the fact that int x = (int)y will get the integer part of y and put it in x.
After that, you just have to check whether x==y or not.

Combining methods that are the same but take in different variables

I have a method I use to take in a number and return the number in a notation format. I'm using doubles, floats, and ints in my code so I have three of the same methods written with only the intake variable different for them. Is there a way I can get the same effect with only 1 method?
To try and explain further. I want to create a method that accepts multiple variable types to it. Instead of the method calling for a double, I'd like it to accept a variable if it's an int, a float, or a double without casting. Right now I have 3 copies of the same method, each one accepting a different variable. I don't want to change all the variables I'm using to doubles for other reasons within the code.
Is there any way I can use one method that accepts all three variable types instead of having 3, each one accepting only one variable type.
public string NotationMethod(double x, string y)
{
if (x > 1000)
{
var exponent = Math.Floor(Math.Log10(Math.Abs(x)));
var mantissa = x / Math.Pow(10, exponent);
return mantissa.ToString("F2") + "e" + exponent;
}
return x.ToString("F0");
}
public string NotationMethod(int x, string y)
{
if (x > 1000)
{
var exponent = Math.Floor(Math.Log10(Math.Abs(x)));
var mantissa = x / Math.Pow(10, exponent);
return mantissa.ToString("F2") + "e" + exponent;
}
return x.ToString("F0");
}
public string NotationMethod(float x, string y)
{
if (x > 1000)
{
var exponent = Math.Floor(Math.Log10(Math.Abs(x)));
var mantissa = x / Math.Pow(10, exponent);
return mantissa.ToString("F2") + "e" + exponent;
}
return x.ToString("F0");
}
I noticed that you are using Math.Floor() in each case. I think you can simply use the method with first parameter Double data type. You will just need to convert the inputs to Double while calling the method.

Return Integers in Base 10

I've been trying to understand how one would input an integer and have a function return the digits in base 10 in C#. I've researched around and can't find many code examples to work with other than the math formulas.
Thanks!
It sounds like you just want:
int value = 2590123;
string text = value.ToString();
That will automatically use base 10... at least in all the cultures I'm aware of. If you really want to make sure, use the invariant culture:
string text = value.ToString(CultureInfo.InvariantCulture);
Note that the concept of a base only makes sense when you talk about some representation with separate "digits" of some form - such as a string representation. A pure number doesn't have a base - if you have 16 apples, that's the same number as if you've got 0x10 apples.
EDIT: Or if you want to write a method to return the sequence of digits as integers, least significant first:
// Note that this won't give pleasant results for negative input
static IEnumerable<int> GetDigits(int input)
{
// Special case...
if (input == 0)
{
yield return 0;
yield break;
}
while (input != 0)
{
yield return input % 10;
input = input / 10;
}
}
Making a whole lot of assumptions, I'm guessing you want something like this:
// All ints are "base 10"
var thisIsAlreadyBase10 = 10;
Console.WriteLine("The number {0} in base 10 is {0}", thisIsAlreadyBase10);
// However, if you have a string with a non-base 10 number...
var thisHoweverIsAStringInHex = "deadbeef";
Console.WriteLine(
"The hex string {0} == base 10 int value {1}",
thisHoweverIsAStringInHex,
Convert.ToInt32(thisHoweverIsAStringInHex, 16));

How to ignore Decimal

I have tried to do this - Making any float value to int value. What I tried to achieve is make it 2.00-2.99 goes to 2.
Note: Im not trying to do Approximation (lower than 2.49 goes to 2, and those 2.50+ goes to 3).
I have done this so far
public int RemoveDecimal(float value)
{
string TempText = (string)value;
TempText.Remove(IndexOf('.'));
return int.parse(TempText);
}
But this will get an error when the float value ends with .00
How can I achieve this?
Thanks for any help
Math.Floor is the function you need.
It:
Returns the largest integer less than or equal to the specified number.
Example:
var val = Math.Floor(value);
Or, you could simply cast to an integer - this will simply ignore the decimal portion, so long as the range of the decimal is within the range of an int (otherwise you will get an exception):
int noDecimals = (int)value;
you can't always convert a float to an int because most of the values in float are out of range for int. you should return a string.
the following will do just that.
public string RemoveDecimal(float value)
{
string TempText = value.ToString("#");
return TempText;
}
Simply casting a floating point number to int does what you want.
i = (int)myFloat;
It truncates the fractional digits, i.e. it always goes in the direction of 0.
(int)2 == 2
(int)1.9 == 1
(int)-1.5 == -1
This will obviously not work correctly if the result is outside the valid range of int. If you want to achieve the same thing, but with a floating point number as result, Math.Truncate is what you need.

Finding the number of places after the decimal point of a Double

I have a Double value:
double a = 4.5565;
What is the easiest way to calculate the number of digits after the decimal point (4 in this case).
I know that I can convert to string and do a split and take the length. But is there an easier way?
There's no easy way, especially since the number of digits mathematically speaking might be far more than displayed. For example, 4.5565 is actually stored as 4.556499999999999772626324556767940521240234375 (thanks to harold for calculating that). You're very unlikely to find a useful solution to this problem.
EDIT
You could come up with some algorithm that works like this: if, as you calculate the decimal representation, you find a certain number of 9s (or zeros) in succession, you round up (or down) to the last place before the series of 9s (or zeros) began. I suspect that you would find more trouble down that road than you would anticipate.
var precision = 0;
var x = 1.345678901m;
while (x*(decimal)Math.Pow(10,precision) !=
Math.Round(x*(decimal)Math.Pow(10,precision)))
precision++;
precision will be equal to the number of significant digits of the decimal value (setting x to 1.23456000 will result in a precision of 5 even though 8 digits were originally specified in the literal). This executes in time proportional to the number of decimal places. It counts the number of fractional digits ONLY; you can count the number of places to the left of the decimal point by taking the integer part of Math.Log10(x). It works best with decimals as they have better value precision so there is less rounding error.
Write a function
int CountDigitsAfterDecimal(double value)
{
bool start = false;
int count = 0;
foreach (var s in value.ToString())
{
if (s == '.')
{
start = true;
}
else if (start)
{
count++;
}
}
return count;
}
I think this might be a solution:
private static int getDecimalCount(double val)
{
int i=0;
while (Math.Round(val, i) != val)
i++;
return i;
}
double val9 = 4.5565d; int count9 = getDecimalCount(val9);//result: 4
Sorry for the duplication -> https://stackoverflow.com/a/35238462/1266873
base on james answer bat much clearer:
int num = dValue.ToString().Length - (((int)dValue).ToString().Length + 1);
num is the exact number of digits after the decimal point.
without including 0 like this(25.520000)
in this case, you will get num= 2
I Think String solution is best : ((a-(int)a)+"").length-2
I'll perhaps use this code if I needed,
myDoubleNumber.ToString("R").Split('.')[1].Length
"R" here is Round Trip Format Specifier
We need to check for the index bounds first of course.
Another solution would be to use some string functions:
private int GetSignificantDecimalPlaces(decimal number, bool trimTrailingZeros = true)
{
var stemp = Convert.ToString(number);
if (stemp.IndexOf(Application.CurrentCulture.NumberFormat.NumberDecimalSeparator) < 0)
return 0;
if (trimTrailingZeros)
stemp = stemp.TrimEnd('0');
return stemp.Length - 1 - stemp.IndexOf(Application.CurrentCulture.NumberFormat.NumberDecimalSeparator);
}
Remember to use System.Windows.Forms to get access to Application.CurrentCulture

Categories

Resources