C# Extension Method to Calculate Position Between a Range - c#

I am trying to write an extension method off a 'decimal' that calculates the value of a given number in relation to a given lower and upper range. I know that sounds a bit strange so here is a concrete example.
Lets say that there is a pay grade system in place at a particular place of work and the pay rate categories are as follows..
Cat1 (0 - 20 hours) = $20/hour
Cat2 (20 - 30 hours) = $22/hour
Cat3 (30 - 40 hours) = $24/hour
Cat4 (40 - 50 hours) = $26/hour
Cat5 (50+ hours) = $28/hour
So...
If a person worked 14 hours in a given week, they would earn (14 * 20)
If a person worked 27 hours in a given week, they would earn (20 * 20) + (7 * 22)
If a person worked 38 hours in a given week, they would earn (20 * 20) + (10 * 22) + (8 * 24)
and so on..
The extension method I have put together looks like this and its purpose is to return a single decimal that tells me if it falls into the given range or not. if it does it tells me how much by. if not it returns zero or the maximum value for that range. To be honest something about it doesnt seem right.
Can anyone verify that this is the correct logic and perhaps if there is anyway to optimise it?
public static decimal ValueBetween(this decimal m, decimal lower, decimal upper = decimal.MaxValue)
{
return (m > lower)
? (m > upper)
? upper - lower
: m - lower
: 0m;
}
Example Usage with Expected Output
((decimal)14).ValueBetween(0, 20) = 14
((decimal)24).ValueBetween(0, 20) = 20
((decimal)24).ValueBetween(20, 30) = 4
((decimal)24).ValueBetween(30, 40) = 0
((decimal)150).ValueBetween(40) = 110
Thanks.

I think what you have is fine, except maybe you could make it a bit more readable:
public static decimal ValueBetween(this decimal m, decimal lower, decimal upper = decimal.MaxValue)
{
if (m < lower) return 0M;
if (m > upper) return upper - lower;
return m - lower;
}

Related

Find first digit of a number using ONLY integer operations

I can't understand how to solve the problem that the teacher gave me.
Given a number N (0 <= N <= 100), find its first digit.
For example:
input: 100
result: 1
input: 46
result: 4
input: 3
result: 3
It seemed easy at first, but (as the teacher said) it should be done using ONLY integer data types (in other words, using +, -, *, / and % operators). Is it even possible to do it this way?
I just can't realize how to extract the first digit from a variable-length number without using things like log10, conditions, "while" loop or string conversion.
Without any conditionals:
int H= N / 100; // Hundreds digit
int T= (N / 10) % 10; // Tens digit
int U= N % 10; // Units digit
int h= H; // Hundreds flag
int t= (T + 9) / 10 * (1 - h); // Tens flag
int u= (1 - t) * (1 - h); // Units flag
int Answer= u * U + t * T + h * H; // Combination
Edit: Now tested for 0 and 100:
var result = n / 10 * (1 - n / 100) + n / 100 + (109 - n) / 100 * n;
How it works:
n | n / 10 * (1 - n / 100) | n / 100 | (109 - n) / 100 * n
-----------------------------------------------------------------
10 - 99 | 1 - 9 | 0 | 0
-----------------------------------------------------------------
100 | 0 | 1 | 0
-----------------------------------------------------------------
0 - 9 | 0 | 0 | 0 - 9
Use a while loop, and keep dividing the input number by 10, so long as we are starting with a value which is greater than or equal to 10. When the modified input is less than ten, then it means we have stripped off all digits to the right, except for the "first" digit.
int input = 100;
while (input >= 10)
{
input /= 10;
}
Console.WriteLine("First digit is: {0}", input);
Demo
This is a non-generic response, and only works because the domain is limited. The idea is to return all the digits (hundred's, ten's, and one's) smooshed together." Some thoughts on specific ranges of numbers:
100 is easy because the ten's and one's units are both zero. There are no other three digit numbers, which is good, because anything with a non-zero one's or ten's place will cause problems below.
All numbers less than 100 can include the hundred's digit in the response because it will always be zero.
Any multiple of 10 is easy, just include the each hundred's ten's and one's value, because the other digits are zero.
The tricky part is the one's place. There needs to be a way to "cancel out" this value if a larger digit is supposed to be returned. For example, 87, we want the 8 but want to cancel out the 7.
This leads to the idea
(ten - 9)*(ten - 8)*(ten - 7)*(ten - 6)*(ten - 5)*(ten - 4)*(ten - 3)*(ten - 2)*(ten - 1)
What happens is that any time the ten's place is non-zero, the above will evaluate to zero. So we can multiply the one's place by this to zero out the one's place when the ten's place is non-zero. However, there's a problem when the ten's place is zero. In that case, we're off by a factor of 9! (nine factorial = 362880) and the wrong sign. This is why an extra minus sign is included, and divide out by 362880 to get the right answer when ten's place is zero.
public int GetFirstDigit(int n)
{
var hundred = (n % 1000) / 100;
var ten = (n % 100) / 10;
var one = n % 10;
return hundred + ten + one*
(
-(ten - 9)*(ten - 8)*(ten - 7)*(ten - 6)*(ten - 5)*(ten - 4)*(ten - 3)*(ten - 2)*(ten - 1)
) / 362880
;
}
check with
Enumerable.Range(0, 101).ToList().ForEach(x => Console.WriteLine(x + ": " + GetFirstDigit(x)));
I tried to solve the case but without success,
I can only achieve finding the first digit if the N is 1 - 100.
Here is my source code for it. Hope it helps
https://dotnetfiddle.net/6XyOfd
static int Result(int input)
{
return input/100 + (input%100/input)*input/10 + (input%10/input)*input;
}
input/100 will return 1 if and only if input equals 100, else 0
(input%100/input) will return 1 if and only if input < 100, else 0
if input is lower than 10, input/10 will be 0
(input%10/input) will return 1 if and only if input < 10, else 0
Caution
This would break if input == 0, see #quanik's answer to handle 0.
However, it will work for 1-999.
if (N < 10)
Output(N)
else if (N < 100)
Output(N / 10)
else
Output(1)

How to calculate the infinite value of a division? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to know the repeating decimal in a fraction?
1/3 is different by 3/10. 0.33333 != 0.3
So 1/3 will be 0.3 (with a line above number three)
1/12 = 0.833333 = 0.083 (with a line above number three)
1/13 = 0.076923076923 = 0.|076923|
Those lines represent the repeating part.
I plan to have this model in a class. I'm a bit lost on this situation. I just need some ideas to know determine the repeating value. Thanks.
Cycle detection algorithm is the answer. You can use Floyd's cycle detection algorithm or Brent's cycle detection algorithm.
The function to plug into those algorithms is the function to produce the next digit of the quotient.
At each step, divide, floor, take the remainder, multiply that by ten, repeat until you get the same number.
For example, for 1/81:
1/81 = 0 with remainder 1 0
10/81 = 0 with remainder 10 0.0
100/81 = 1 with remainder 19 0.01
190/81 = 2 with remainder 28 0.012
280/81 = 3 with remainder 37 0.0123
...
10/81 = 0 with remainder 10; saw this already.
0.|012345679|
Here's a sample implementation:
private static string GetRepeatingPart(int n, int d) {
var seen = new HashSet<int>();
var result = new StringBuilder();
n = (n % d) * 10;
while(true) {
int p = n / d;
n = (n % d) * 10;
if(seen.Contains(n)) {
return result.ToString();
}
result.Append(p);
seen.Add(n);
}
}

C# How to calculate first 10 numbers out a bill number of 12?

Lets assume i have a bill number that has 12 numbers: 823 45678912
My question is how exactly do i do calculations with the first 10 numbers?
To verify if a given in billnumber is correct i have to perform the following calculation:
(first 10 numbers) % 97 = result
And if the result of the calculation is the same as the last 2 numbers of my bill number, then it is verified.
Thanks in advance.
(n / 100) % 97 == n % 100
It looks like you have a bill number that is actually a string with spaces. I would use #Marcelo's solution, but first you'll need to convert it to a long integer. This should help with that.
var billAsNumber = long.Parse( billNumber.Replace(" ","") );
var valid = (billAsNumber / 100) % 97 == billAsNumber % 100;
If your bill number is stored in a long variable, shift it right two places and there you have it:
var first10Digits = billNumber / 100;
var checksum = first10Digits % 97;
Note that your bill number might have more than 12 digits and the resulting integer would not fit into an existing data type. While searching for solutions on how to do MOD 97 division on very large numbers i've found this algorithm that worked well for me.

Append a digit to an integer and make sure sum of each digits ends with 1

What is the algorithm in c# to do this?
Example 1:
Given n = 972, function will then append 3 to make 9723, because 9 + 7 + 2 + 3 = 21 (ends with 1). Function should return 3.
Example 2:
Given n = 33, function will then append 5 to make 335, because 3 + 3 + 5 = 11 (ends with 1). Function should return 5.
Algorithms are language independent. Asking for "an algorithm in C#" doesn't make much sense.
Asking for the algorithm (as though there is only one) is similarly misguided.
So, let's do this step by step.
First, we note that only the last digit of the result is meaningful. So, we'll sum up our existing digits, and then ignore all but the last one. A good way to do this is to take the sum modulo 10.
So, we have the sum of the existing digits, and we want to add another digit to that, so that the sum of the two ends in 1.
For the vast majority of cases, that will mean sum + newDigit = 11. Rearranging gives newDigit = 11 - sum
We can then take this modulo 10 (again) in order to reduce it to a single digit.
Finally, we multiply the original number by 10, and add our new digit to it.
The algorithm in general:
(10 - (sum of digits mod 10) + 1) mod 10
The answer of the above expression is your needed digit.
sum of digits mod 10 gives you the current remainder, when you subtract this from 10 you get the needed value for a remainder of 0. When you add 1 you get the needed value to get a remainder of 1. The last mod 10 gives you the answer as a 1 digit number.
So in C# something like this:
static int getNewValue(string s)
{
int sum = 0;
foreach (char c in s)
{
sum += Convert.ToInt32(c.ToString());
}
int newDigit = (10 - (sum % 10) + 1) % 10;
return newDigit;
}
Another alternative using mod once only
int sum = 0;
foreach (char c in s)
sum += Convert.ToInt32(c.ToString());
int diff = 0;
while (sum % 10 != 1)
{
sum++;
diff++;
}
if (diff > 0)
s += diff.ToString();
Well, it's easier in C++.
std::string s = boost::lexical_cast<string>( i );
i = i * 10 + 9 - std::accumulate( s.begin(), s.end(), 8 - '0' * s.size() ) % 10;
Addicted to code golf…

rounding to the best unit without losing precision

I receive a decimal number with a maximum of 4 digits after the "." and I know this number is in milligram.
I have to find the best matching unit (milligram, gram, kilogram) for the number.
for an example if I receive
edited
116000000.0000 milligram, it's going to return 116.0000 kilogram
66990000.0000 milligram, it's going to return 66.9900 kilogram
49000010.0000 milligram, it's going to return 49000.0100 g
49000000.0100 milligram, it's going to return 49000000.0100 milligram
1001 milligram, it's going to return 1.0010 gram
1010 milligram, it's going to return 1.0100 gram
1000 milligram, it's going to return 0.0010 kilogram
1100 milligram, it's going to return 0.0011 kilogram
135005 milligram, it's going to return 135.0050 gram
and last sample 10013500 milligram, it's going to return 10.0135 kilogram
I'm currently using this code, which I think look/is ugly and can fail
Dim temp As Decimal
Dim u = New List(Of Integer)(New Integer() {1, 1000, 1000000})
For i = 0 To u.Count - 1
temp = CDec(qty / u(i))
If (temp * 10000) - Math.Truncate(temp * 10000) <> 0 AndAlso (temp * 10000) - Math.Truncate(temp * 10000) < 1 Then
temp = CDec(qty / u(i - 1))
Exit For
End If
Next
qty = temp
is there a better/nicer way of doing what I do?
edit for precision
the input can be any decimal between 0.0001 and maximum that a decimal can accept in .net
the output need to be rounded to the best unit with a maximum of 4 digits after "." without losing any precision
Gen the numbers and choose the suitable one.
public static decimal FormatDecimal(decimal i)
{
decimal milli = i;
decimal grams = decimal.Round(i / 1000m, 4);
decimal kilo = decimal.Round(grams / 1000m, 4);
if (kilo * 1000 * 1000 == milli)
{
return kilo;
}
if (grams * 1000 == milli)
{
return grams;
}
return milli;
}
And to test:
public static void FormatDecimalTest()
{
if (FormatDecimal(116000000.0000m) == 116.0000m)
Console.WriteLine("ok1");
if (FormatDecimal(66990000.0000m) == 66.9900m)
Console.WriteLine("ok2");
if (FormatDecimal(49000010.0000m) == 49000.0100m)
Console.WriteLine("ok3");
if (FormatDecimal(49000000.0100m) == 49000000.0100m)
Console.WriteLine("ok4");
if (FormatDecimal(1001m) == 1.0010m)
Console.WriteLine("ok5");
if (FormatDecimal(1000m) == 0.0010m)
Console.WriteLine("ok6");
if (FormatDecimal(1100m) == 0.0011m)
Console.WriteLine("ok7");
if (FormatDecimal(1100m) == 0.0011m)
Console.WriteLine("ok8");
if (FormatDecimal(135005m) == 135.0050m)
Console.WriteLine("ok9");
if (FormatDecimal(10013500m) == 10.0135m)
Console.WriteLine("ok10");
}
In your question, I see you used a loop over the various factors. Here's a looping solution that will find the first factor that does not lose precision.
public static decimal FormatDecimal(decimal i)
{
List<decimal> myFactors = new List<decimal>()
{ 1000m * 1000m, 1000m};
foreach (decimal conversionFactor in myFactors)
{
decimal result = decimal.Round(i / conversionFactor, 4);
if (result * conversionFactor == i)
{
return result;
}
}
return i;
}
Why don't you just use ifs? something like:
if (num > 1000000)
return string.format("{0.####} kg", num/1000000)
if (num > 1000)
return string.format("{0.####} g", num/1000);
return string.format("{0.####} mg", num);
I wouldn't be above doing a CStr on the number, counting the characters, removing all trailing zeros, counting the number again, and deciding on a unit based on the number of characters in your string. Then just divide the original number by the correct magnitude and append the unit.
Before doing that, though, you'd want to do a Truncate on the original and see if the returned value matches the original; then you just use mg.
Probably won't work any better than your code, but it might be easier to read. Maybe.
Your sample doesn't make too much sense, but your should go with something like this:
static string FormatWeight(double value)
{
if (value > 10000000) return (value / 10000000D).ToString("0.#### t");
if (value > 100000) return (value / 100000D).ToString("0.#### kg");
if (value > 1000) return (value / 1000D).ToString("0.#### g");
return value.ToString("0.#### mg");
}
would you not be better either implementing or using a unit library for the conversions, then formatting the results afterwards?
some projects here and here, although I can't vouch for the quality of any of it...
and java one discussed here
so if I understood correctly, any argument ARG which comes with a fraction <> 0 will stay as is and expressed in mg ... this should be easy to code
If ARG <> Int(ARG) Then
' Return ARG
Endif
anything without a fraction should be converted to the most appropriate unit (mg, g, dag, kg, t, etc). So for these we need to to look at the argument as a string and count the "0"es from the back-end and see from there how often we may divide by 10 without loosing numeric precision.
In your first example we count 6 Zeroes from the backend, so we could safely divide by 10^(6+4) to get not more than 4 fractional digits (which is more than we actually need).
In your last example we count 2 "0"es from the back, so we can safely divide by 10^(2+4).
So if the "save division power" is >=6, divide by 10^6 and express in kg
if the "save division power is between 5 and 3, divide by 10^3 and express in g, below 3 leave as mg.
Hope that helps.

Categories