Can Math.Round in C# be used for whole integer values? - c#

I have integer 363 for example.
Any method to make it 360 or 365?

This is a hack, but it works:
var rounded = Math.Round(363 / 5f) * 5;

There's nothing built-in, you're just going to have to code the logic yourself. Here's one such method. (Going down is clearer, but going up is manageable.)
int number = 363;
int roundedDown = number - number % 5;
int roundedUp = number + (number % 5 > 0 ? (5 - number % 5) : 0);
Edit for negative numbers, the logic almost gets reversed.
static int RoundUpToFive(int number)
{
if (number >= 0)
return number + (number % 5 > 0 ? (5 - number % 5) : 0);
else
return number - (number % 5);
}
static int RoundDownToFive(int number)
{
if (number >= 0)
return number - number % 5;
else
return number + (number % 5 < 0 ? (-5 - number % 5) : 0);
}

Here's what I usually do, which is a combination of the two ideas:
static int RoundDown(int x, int n) {
return x / n * n;
}
static int Round(int x, int n) {
return (x + n / 2) / n * n;
}
static int RoundUp(int x, int n) {
return (x + n - 1) / n * n;
}
(That assumes positive numbers; Extending it to negatives is straight-forward.)
[edit]
According to LLVM, the Round function can also be written like this:
int Round(int x, int n) {
int z = (x + n / 2);
return z - (z % n);
}
Which you may find more elegant.

Related

I am trying to find a value of multiple factorials . both values will be divided by like 100!/98! =?

static void Main(string[] args)
{
Console.WriteLine("Enter your number: ");
int number= Convert.ToInt32(Console.ReadLine());
int number2 = Convert.ToInt32(Console.ReadLine());
double factorial = Factorial(number,number2);
Console.WriteLine("Factorial of " + number +" / "+ number2 + " = " + factorial );
Console.ReadKey();
}
//Factorial function added
public static double Factorial(int number, int number2)
{
if (number == 1 && number2 ==1 )
{
return 1;
}
double factorial = 1;
double factorial1 = 1;
double factorial2 = 1;
for (int i = number, j = number2; i >= 1 && j >= 1; i--, j--)
{
factorial1 = (factorial * i);
factorial2 = (factorial * j);
factorial = factorial1 / factorial2;
}
return factorial;
}
Your attempted solution is simply so overcomplicated, I wouldn't know where to begin. This usually happens when you don't stop to think about how you'd resolve this problem by hand:
So, the question is, whats 5!/3!? Ok, lets write it out:
(5 * 4 * 3 * 2 * 1) / (3 * 2 * 1)
Wow, that looks like it can be simplified simply to 5 * 4.
The key insight here is that m! % n! = 0 if n is less or equal to m. In other words, m! is always divisible by n! because there is always an integer r such that r * n! = m!, and you don't need to evaluate m! or n! to figure out what r is, you simple do:
r = m * (m - 1) * (m - 2) * ... * (n + 1); // m >= n
If n > m, r is zero unless you are looking for a real number solution in which case you would simply evaluate r as n! / m! and then return 1.0 / r because m! / n! = 1 / (n! / m!).
How to evaluate r?
public static long DivideFactorials(int m, int n)
{
if (n > m)
return 0;
var r = 1L;
for (var k = m; k > n; k--)
r *= k;
return r;
}
Or the real number solution:
public static double DivideFactorials(int m, int n)
{
if (n > m)
return 1 / DivideFactorials(n, m);
var r = 1.0;
for (var k = m; k > n; k--)
r *= k;
return r;
}
If I had to save your try:
public static double Factorial(int number, int number2)
{
if (number == 1 && number2 == 1)
{
return 1;
}
double facNum = 1;
double facNum2 = 1;
// counting up is easier, we start at 2 as we initialized to 1
// we count up to the max of both numbers
for (int i = 2; i <= Math.Max(number, number2); i++)
{
if (i <= number)
facNum *= i; // we mult this until we reached number
if (i <= number2)
facNum2 *= i; // we mult this until we reach number2
}
// return the devision of both - this wont handle number < number2 well!
return facNum / facNum2; // do this outside the loop
}
If I had to create a solution:
Factorial division of integers has 3 outcomes (I can think of):
N! / O! with N == O:
let N=3, O=3
N! = 1*2*3
O! = 1*2*3
N! / O! = 1*2*3/(1*2*3) == 1
N! / O! with N > O:
let N=5, O=3
N! = 1*2*3*4*5
O! = 1*2*3
N! / O! == 1*2*3*4*5/(1*2*3) == 4*5 == 20
N! / O! with N < O:
let N=3, O=5
N! = 1*2*3
O! = 1*2*3*4*5
N! / O! == 1*2*3/(1*2*3*4*5) == 1/(4*5) == 1/20
Based on this I would model the problem like that:
using System;
using System.Collections.Generic;
using System.Linq;
internal class Program
{
public static decimal CalcFactDivision(int n1, int n2)
{
// calclulate the division of a factorial by another, num1 must be >= num2
IEnumerable<int> getRemaining(int num1, int num2)
{
// special cases: div by 0 and 0 div something
if (num2 == 0)
num2 = 1; // 0! == 1
else if (num1 == 0)
return new[] { 0 };
// get all numbers that make up the factorial in one step
// I can guarantee that num1 will always be bigger then num2
// by how I call this
return Enumerable.Range(num2 + 1, num1 - num2);
}
// calculate the product of an ienumerable of ints
int product(IEnumerable<int> nums) => nums.Aggregate((a, b) => a * b);
if (n1 == n2)
return 1;
else if (n1 > n2) // use product(...) to calc
return product(getRemaining(n1, n2));
else // flip them and use 1/product(...) to calc
return (decimal)1 / product(getRemaining(n2, n1));
}
static void Main(string[] args)
{
foreach (var a in Enumerable.Range(1, 10))
Console.WriteLine($"{a}! / {10 - a}! = {CalcFactDivision(a, 10 - a)} ");
Console.ReadLine();
}
}
Output:
1! / 9! = 0,0000027557319223985890652557
2! / 8! = 0,0000496031746031746031746032
3! / 7! = 0,0011904761904761904761904762
4! / 6! = 0,0333333333333333333333333333
5! / 5! = 1
6! / 4! = 30
7! / 3! = 840
8! / 2! = 20160
9! / 1! = 362880
10! / 0! = 3628800

BBP algorithm get nth digit of PI?

I am trying to turn the BBP Formula (Bailey-Borwein-Plouffe) in to C# code, it is digit extraction of pi in base 16 (spigot algorithm), the idea is give the input of what index/decimal place you want of pi then get that single digit. Let's say I want the digit that are at the decimal place/index 40000 (in base 16) without having to calculate pi with 40000 decimals because I don't care about the other digits.
Anyhow here is the math formula, (doesn't look like it should be to much code? )
Can't say I understand 100% what the formal mean, if I did I probably be able to make it in to code, but from my understanding looking at it.
Is this correct?
pseudo code
Pi = SUM = (for int n = 0; n < infinity;n++) { SUM += ((4/((8*n)+1))
- (2/((8*n)+4)) - (1/((8*n)+5)) - (1/((8*n)+6))*((1/16)^n)) }
Capital sigma basically is like a "for loop" to sum sequences together?
example
and in C# code:
static int CapSigma(int _start, int _end)
{
int sum = 0;
for(int n = _start; n <= _end; n++)
{
sum += n;
}
return (sum);
}
Code so far (not working):
static int BBPpi(int _precision)
{
int pi = 0;
for(int n = 0; n < _precision; n++)
{
pi += ((16 ^ -n) * (4 / (8 * n + 1) - 2 / (8 * n + 4) - 1 / (8 * n + 5) - 1 / (8 * n + 6)));
}
return (pi);
}
I'm not sure how to make it in to actual code also if my pseudo code math is correct?
How to sum 0 to infinity? Can't do it in a for loop and also where in the formula is the part ("input") that specify what nth (index) digit you want to get out? is it the start n (n = 0)? so too get digit 40000 would be n =40000?
You need to cast to double :
class Program
{
static void Main(string[] args)
{
double sum = 0;
for (int i = 1; i < 100; i++)
{
sum += BBPpi(i);
Console.WriteLine(sum.ToString());
}
Console.ReadLine();
}
static double BBPpi(int n)
{
double pi = ((16 ^ -n) * (4.0 / (8.0 * (double)n + 1.0) - 2 / (8.0 * (double)n + 4.0) - 1 / (8.0 * (double)n + 5.0) - 1.0 / (8.0 * (double)n + 6.0)));
return (pi);
}
}

Average of 3 long integers

I have 3 very large signed integers.
long x = long.MaxValue;
long y = long.MaxValue - 1;
long z = long.MaxValue - 2;
I want to calculate their truncated average. Expected average value is long.MaxValue - 1, which is 9223372036854775806.
It is impossible to calculate it as:
long avg = (x + y + z) / 3; // 3074457345618258600
Note: I read all those questions about average of 2 numbers, but I don't see how that technique can be applied to average of 3 numbers.
It would be very easy with the usage of BigInteger, but let's assume I cannot use it.
BigInteger bx = new BigInteger(x);
BigInteger by = new BigInteger(y);
BigInteger bz = new BigInteger(z);
BigInteger bavg = (bx + by + bz) / 3; // 9223372036854775806
If I convert to double, then, of course, I lose precision:
double dx = x;
double dy = y;
double dz = z;
double davg = (dx + dy + dz) / 3; // 9223372036854780000
If I convert to decimal, it works, but also let's assume that I cannot use it.
decimal mx = x;
decimal my = y;
decimal mz = z;
decimal mavg = (mx + my + mz) / 3; // 9223372036854775806
Question: Is there a way to calculate the truncated average of 3 very large integers only with the usage of long type? Don't consider that question as C#-specific, just it is easier for me to provide samples in C#.
This code will work, but isn't that pretty.
It first divides all three values (it floors the values, so you 'lose' the remainder), and then divides the remainder:
long n = x / 3
+ y / 3
+ z / 3
+ ( x % 3
+ y % 3
+ z % 3
) / 3
Note that the above sample does not always work properly when having one or more negative values.
As discussed with Ulugbek, since the number of comments are exploding below, here is the current BEST solution for both positive and negative values.
Thanks to answers and comments of Ulugbek Umirov, James S, KevinZ, Marc van Leeuwen, gnasher729 this is the current solution:
static long CalculateAverage(long x, long y, long z)
{
return (x % 3 + y % 3 + z % 3 + 6) / 3 - 2
+ x / 3 + y / 3 + z / 3;
}
static long CalculateAverage(params long[] arr)
{
int count = arr.Length;
return (arr.Sum(n => n % count) + count * (count - 1)) / count - (count - 1)
+ arr.Sum(n => n / count);
}
NB - Patrick has already given a great answer. Expanding on this you could do a generic version for any number of integers like so:
long x = long.MaxValue;
long y = long.MaxValue - 1;
long z = long.MaxValue - 2;
long[] arr = { x, y, z };
var avg = arr.Select(i => i / arr.Length).Sum()
+ arr.Select(i => i % arr.Length).Sum() / arr.Length;
Patrick Hofman has posted a great solution. But if needed it can still be implemented in several other ways. Using the algorithm here I have another solution. If implemented carefully it may be faster than the multiple divisions in systems with slow hardware divisors. It can be further optimized by using divide by constants technique from hacker's delight
public class int128_t {
private int H;
private long L;
public int128_t(int h, long l)
{
H = h;
L = l;
}
public int128_t add(int128_t a)
{
int128_t s;
s.L = L + a.L;
s.H = H + a.H + (s.L < a.L);
return b;
}
private int128_t rshift2() // right shift 2
{
int128_t r;
r.H = H >> 2;
r.L = (L >> 2) | ((H & 0x03) << 62);
return r;
}
public int128_t divideby3()
{
int128_t sum = {0, 0}, num = new int128_t(H, L);
while (num.H || num.L > 3)
{
int128_t n_sar2 = num.rshift2();
sum = add(n_sar2, sum);
num = add(n_sar2, new int128_t(0, num.L & 3));
}
if (num.H == 0 && num.L == 3)
{
// sum = add(sum, 1);
sum.L++;
if (sum.L == 0) sum.H++;
}
return sum;
}
};
int128_t t = new int128_t(0, x);
t = t.add(new int128_t(0, y));
t = t.add(new int128_t(0, z));
t = t.divideby3();
long average = t.L;
In C/C++ on 64-bit platforms it's much easier with __int128
int64_t average = ((__int128)x + y + z)/3;
You can calculate the mean of numbers based on the differences between the numbers rather than using the sum.
Let's say x is the max, y is the median, z is the min (as you have). We will call them max, median and min.
Conditional checker added as per #UlugbekUmirov's comment:
long tmp = median + ((min - median) / 2); //Average of min 2 values
if (median > 0) tmp = median + ((max - median) / 2); //Average of max 2 values
long mean;
if (min > 0) {
mean = min + ((tmp - min) * (2.0 / 3)); //Average of all 3 values
} else if (median > 0) {
mean = min;
while (mean != tmp) {
mean += 2;
tmp--;
}
} else if (max > 0) {
mean = max;
while (mean != tmp) {
mean--;
tmp += 2;
}
} else {
mean = max + ((tmp - max) * (2.0 / 3));
}
Patching Patrick Hofman's solution with supercat's correction, I give you the following:
static Int64 Avg3 ( Int64 x, Int64 y, Int64 z )
{
UInt64 flag = 1ul << 63;
UInt64 x_ = flag ^ (UInt64) x;
UInt64 y_ = flag ^ (UInt64) y;
UInt64 z_ = flag ^ (UInt64) z;
UInt64 quotient = x_ / 3ul + y_ / 3ul + z_ / 3ul
+ ( x_ % 3ul + y_ % 3ul + z_ % 3ul ) / 3ul;
return (Int64) (quotient ^ flag);
}
And the N element case:
static Int64 AvgN ( params Int64 [ ] args )
{
UInt64 length = (UInt64) args.Length;
UInt64 flag = 1ul << 63;
UInt64 quotient_sum = 0;
UInt64 remainder_sum = 0;
foreach ( Int64 item in args )
{
UInt64 uitem = flag ^ (UInt64) item;
quotient_sum += uitem / length;
remainder_sum += uitem % length;
}
return (Int64) ( flag ^ ( quotient_sum + remainder_sum / length ) );
}
This always gives the floor() of the mean, and eliminates every possible edge case.
Because C uses floored division rather than Euclidian division, it may easier to compute a properly-rounded average of three unsigned values than three signed ones. Simply add 0x8000000000000000UL to each number before taking the unsigned average, subtract it after taking the result, and use an unchecked cast back to Int64 to get a signed average.
To compute the unsigned average, compute the sum of the top 32 bits of the three values. Then compute the sum of the bottom 32 bits of the three values, plus the sum from above, plus one [the plus one is to yield a rounded result]. The average will be 0x55555555 times the first sum, plus one third of the second.
Performance on 32-bit processors might be enhanced by producing three "sum" values each of which is 32 bits long, so that the final result is ((0x55555555UL * sumX)<<32) + 0x55555555UL * sumH + sumL/3; it might possibly be further enhanced by replacing sumL/3 with ((sumL * 0x55555556UL) >> 32), though the latter would depend upon the JIT optimizer [it might know how to replace a division by 3 with a multiply, and its code might actually be more efficient than an explicit multiply operation].
If you know you have N values, can you just divide each value by N and sum them together?
long GetAverage(long* arrayVals, int n)
{
long avg = 0;
long rem = 0;
for(int i=0; i<n; ++i)
{
avg += arrayVals[i] / n;
rem += arrayVals[i] % n;
}
return avg + (rem / n);
}
You could use the fact that you can write each of the numbers as y = ax + b, where x is a constant. Each a would be y / x (the integer part of that division). Each b would be y % x (the rest/modulo of that division). If you choose this constant in an intelligent way, for example by choosing the square root of the maximum number as a constant, you can get the average of x numbers without having problems with overflow.
The average of an arbitrary list of numbers can be found by finding:
( ( sum( all A's ) / length ) * constant ) +
( ( sum( all A's ) % length ) * constant / length) +
( ( sum( all B's ) / length )
where % denotes modulo and / denotes the 'whole' part of division.
The program would look something like:
class Program
{
static void Main()
{
List<long> list = new List<long>();
list.Add( long.MaxValue );
list.Add( long.MaxValue - 1 );
list.Add( long.MaxValue - 2 );
long sumA = 0, sumB = 0;
long res1, res2, res3;
//You should calculate the following dynamically
long constant = 1753413056;
foreach (long num in list)
{
sumA += num / constant;
sumB += num % constant;
}
res1 = (sumA / list.Count) * constant;
res2 = ((sumA % list.Count) * constant) / list.Count;
res3 = sumB / list.Count;
Console.WriteLine( res1 + res2 + res3 );
}
}
I also tried it and come up with a faster solution (although only by a factor about 3/4). It uses a single division
public static long avg(long a, long b, long c) {
final long quarterSum = (a>>2) + (b>>2) + (c>>2);
final long lowSum = (a&3) + (b&3) + (c&3);
final long twelfth = quarterSum / 3;
final long quarterRemainder = quarterSum - 3*twelfth;
final long adjustment = smallDiv3(lowSum + 4*quarterRemainder);
return 4*twelfth + adjustment;
}
where smallDiv3 is division by 3 using multipliation and working only for small arguments
private static long smallDiv3(long n) {
assert -30 <= n && n <= 30;
// Constants found rather experimentally.
return (64/3*n + 10) >> 6;
}
Here is the whole code including a test and a benchmark, the results are not that impressive.
This function computes the result in two divisions. It should generalize nicely to other divisors and word sizes.
It works by computing the double-word addition result, then working out the division.
Int64 average(Int64 a, Int64 b, Int64 c) {
// constants: 0x10000000000000000 div/mod 3
const Int64 hdiv3 = UInt64(-3) / 3 + 1;
const Int64 hmod3 = UInt64(-3) % 3;
// compute the signed double-word addition result in hi:lo
UInt64 lo = a; Int64 hi = a>=0 ? 0 : -1;
lo += b; hi += b>=0 ? lo<b : -(lo>=UInt64(b));
lo += c; hi += c>=0 ? lo<c : -(lo>=UInt64(c));
// divide, do a correction when high/low modulos add up
return hi>=0 ? lo/3 + hi*hdiv3 + (lo%3 + hi*hmod3)/3
: lo/3+1 + hi*hdiv3 + Int64(lo%3-3 + hi*hmod3)/3;
}
Math
(x + y + z) / 3 = x/3 + y/3 + z/3
(a[1] + a[2] + .. + a[k]) / k = a[1]/k + a[2]/k + .. + a[k]/k
Code
long calculateAverage (long a [])
{
double average = 0;
foreach (long x in a)
average += (Convert.ToDouble(x)/Convert.ToDouble(a.Length));
return Convert.ToInt64(Math.Round(average));
}
long calculateAverage_Safe (long a [])
{
double average = 0;
double b = 0;
foreach (long x in a)
{
b = (Convert.ToDouble(x)/Convert.ToDouble(a.Length));
if (b >= (Convert.ToDouble(long.MaxValue)-average))
throw new OverflowException ();
average += b;
}
return Convert.ToInt64(Math.Round(average));
}
Try this:
long n = Array.ConvertAll(new[]{x,y,z},v=>v/3).Sum()
+ (Array.ConvertAll(new[]{x,y,z},v=>v%3).Sum() / 3);

Using recursion to add odd numbers

I am trying to write a method to calculate the sum of the odd numbers in all the numbers less than the given number. so eg. CalcOdd(7) would return 5 + 3 + 1 = 9. CalcOdd (10) would return 9 + 7 + 5 + 3 + 1 = 25 etc
The method needs to take in a number, subtract 1, then recursively work backwards adding all odd numbers until it reaches 0. This is what I have so far.
private static int CalcOdd(int n)
{
if (n <= 1)
return 1;
else
if (n % 2 == 0)
n--;
return n + CalcOdd(n - 2);
}
It doesn't work so well, it includes the number passed in in the addition which is not what I want. Can anyone suggest a better way of doing this ? I would also loke to be able to port the answer to work for even numbers and add the option to include the original passed in number in the answer.
Many thanks
Why would you use recursion here? Just loop; or better, figure out the math to do it in a simple equation...
The fact is that C# doesn't make for excellent deep recursion for things like maths; the tail-call isn't really there at the moment.
Loop approach:
private static int CalcOdd(int n)
{
int sum = 0, i = 1;
while (i < n)
{
sum += i;
i += 2;
}
return sum;
}
You could do this with recursion as you say, but if you wish to do it quicker, then I can tell you that the sum of the n first odd numbers is equal to n*n.
private static int CalcOdd(int n) {
if (n<=1)
return 0;
if (n%2 == 1)
n--;
int k = n/2;
return k*k;
}
The reason this works is:
Every even number is of the form 2k, and the odd number before it is 2k-1.
Because 2*1-1 = 1, there are k odd numbers below 2k.
If n is odd, we don't want to include it, so we simply go down to the even number below it and we automatically have what we want.
Edited to fix broken code.
the sum of odd numbers less than a given number is a perfect square.
get the whole part of (n/2) to get the number of odd number less than itself.
square that and voila!
private static int CalcSumOdd(int n)
{
int i;
int.tryParse(n / 2, out i);
return i*i;
}
for even numbers its:
int i = n/2;
return i*(i+1);
correction. The above "even number sum" includes the original number "n". ie fn(12) = 42 = 2 + 4 + 6 + 8 + 10 + 12
if you want to exclude it, you should either unilaterally exclude it, or remove it with logic based on a passed in parameter.
Here is a correction,
int CalcOdd(int n)
{
n--; // <----
if (n <= 1)
return 0; // <----
else
if (n % 2 == 0)
n--;
return n + CalcOdd(n); // <----
}
i'm new here but this seems like a silly recursion exercise, given it can be done with a simple equation:
int sum(n,isEven,notFirst) {
int c=1; //skip the else
if (isEven) c=2;
if (notFirst) n-=2;
return ((n+c)*((n+c)/2))/2; }
classic discrete math sum series..
sum from 1 to 100 (odds and evens) is ((100+1)*(100/2))=5050
edit: in my code here, if you're calculating the sum of odds with n being even, or vice versa, it doesn't work, but i'm not going to put the work into that (and slop the code) right now. i'll assume your code will take care of that by the time it hits the function.. for example 7/2 isn't an int (obviously)
Why use recursion?
private Int32 CalcOdd(Int32 value)
{
Int32 r = 0;
{
while (value >= 1)
{
value--;
if (value % 2 != 0)
{
r += value;
}
}
}
return r;
}
Use a helper function. CalcOdd consists of testing n to see if it is even or odd; if it is even, return helper(n); if it is odd, return helper(n-2).
The helper function must handle three cases:
1) n is less than 1; in this case return 0.
2) n is even, in this case return helper(n-1).
3) n is odd, in this case return n+helper(n-1).
public static int CalcOdd(int n) {
// Find the highest even number. (Either n, or n-1.)
// Divide that by 2, and the answer should be the square of that number.
n = (n & 0x3FFFFFFE) >> 1;
return (int)Math.Pow(n, 2);
}
private static int CalcOdd(int n) {
n -= 1;
if ((n & 1) == 0) n--;
if (n <= 1) return 1;
return n + CalcOdd(n - 1);
}
But I would say doing loops is better and cleaner.
private static int CalcOdd(int n) {
int i, r = 1;
for (i = 3; i < n; i+=2)
r += i;
return r;
}
Since you want the option of including or excluding the first answer (and, keeping your "recursion" constraint in mind):
int calcOdd(int n, bool includeN)
{
if( !includeN )
return calcOdd(n-1, true);
if(n<=1)
return 1;
else
if(n%2 == 0)
n--;
return n+calcOdd(n-1, true);
}
The includeFirst, if passed as true, will include n in the calculations. Otherwise, the next layer down will start "including N".
Granted, as others have said, this is a horribly inefficient use of recursion, but... If you like recursion, try Haskell. It's a language built almost entirely on the concept.
int CalcOdd(int n)
{
n -= 1;
if (n <= 0)
return 0;
if (n % 2 == 0)
n--;
return n + CalcOdd(n);
}
This function is also recursive, and it has parameters which makes you able to decide wether to do even or odd number and wether you want to include the first number or not. If you are confused as to how it works, remember that bools also can be seen as 1 (true) and 0 (false)
int Calc(int n, bool even = false, bool includeFirst = false)
{
n -= !includeFirst;
if (n <= 0)
return 0;
if (n % 2 == even)
n--;
return n + Calc(n - includeFirst, even);
}
HÃ¥kon, I have ported your code to c# in VS 2008 as follows
static int Calc(int n, bool bEven, bool bIncludeFirst)
{
int iEven = Bool2Int(bEven);
int iIncludeFirst = Bool2Int(bIncludeFirst);
n -= 1 - iIncludeFirst;
if (n <= 0)
return 0;
if (n % 2 == iEven)
n--;
return n + Calc(n - iIncludeFirst, bEven, bIncludeFirst);
}
private static int Bool2Int(bool b)
{
return b ? 1 : 0;
}
It seems to be working. Now is there anything I can do to optomise ? i.e. I dont want to have to parse those bools to ints every time etc ?
I'd isolate the 'make it odd' part from the 'sum every other descending number' part: (forgive the Python)
def sumEveryTwoRecursive(n):
if n <= 0:
return 0
return n + sumEveryTwoRecursive(n - 2)
def calcOdd(n):
return sumEveryTwoRecursive(n - (2 if n % 2 else 1))
Just because there isn't one here yet, I've decided to use the LINQ hammer on this nail...
(borrowed from Nick D and Jason's pair programmed answer here)
void Main()
{
GetIterator(7, true, false).Sum().Dump();
// Returns 9
GetIterator(10, true, false).Sum().Dump();
// Returns 25
}
public IEnumerable<int> GetIterator(int n, bool isOdd, bool includeOriginal)
{
if (includeOriginal)
n++;
if (isOdd)
return GetIterator(n, 1);
else
return GetIterator(n, 0);
}
public IEnumerable<int> GetIterator(int n, int odd)
{
n--;
if (n < 0)
yield break;
if (n % 2 == odd)
yield return n;
foreach (int i in GetIterator(n, odd))
yield return i;
}
#include <iostream>
using namespace std;
int sumofodd(int num);
int main()
{
int number,res;
cin>>number;
res=sumofodd(number);
cout<<res;
return 0;
}
int sumofodd(int num)
{ if(num<1) return 0;
if (num%2==0) num--;
return num+sumofodd(num-1);
}

How can you get the first digit in an int (C#)?

In C#, what's the best way to get the 1st digit in an int? The method I came up with is to turn the int into a string, find the 1st char of the string, then turn it back to an int.
int start = Convert.ToInt32(curr.ToString().Substring(0, 1));
While this does the job, it feels like there is probably a good, simple, math-based solution to such a problem. String manipulation feels clunky.
Edit: irrespective of speed differences, mystring[0] instead of Substring() is still just string manipulation
Benchmarks
Firstly, you must decide on what you mean by "best" solution, of course that takes into account the efficiency of the algorithm, its readability/maintainability, and the likelihood of bugs creeping up in the future. Careful unit tests can generally avoid those problems, however.
I ran each of these examples 10 million times, and the results value is the number of ElapsedTicks that have passed.
Without further ado, from slowest to quickest, the algorithms are:
Converting to a string, take first character
int firstDigit = (int)(Value.ToString()[0]) - 48;
Results:
12,552,893 ticks
Using a logarithm
int firstDigit = (int)(Value / Math.Pow(10, (int)Math.Floor(Math.Log10(Value))));
Results:
9,165,089 ticks
Looping
while (number >= 10)
number /= 10;
Results:
6,001,570 ticks
Conditionals
int firstdigit;
if (Value < 10)
firstdigit = Value;
else if (Value < 100)
firstdigit = Value / 10;
else if (Value < 1000)
firstdigit = Value / 100;
else if (Value < 10000)
firstdigit = Value / 1000;
else if (Value < 100000)
firstdigit = Value / 10000;
else if (Value < 1000000)
firstdigit = Value / 100000;
else if (Value < 10000000)
firstdigit = Value / 1000000;
else if (Value < 100000000)
firstdigit = Value / 10000000;
else if (Value < 1000000000)
firstdigit = Value / 100000000;
else
firstdigit = Value / 1000000000;
Results:
1,421,659 ticks
Unrolled & optimized loop
if (i >= 100000000) i /= 100000000;
if (i >= 10000) i /= 10000;
if (i >= 100) i /= 100;
if (i >= 10) i /= 10;
Results:
1,399,788 ticks
Note:
each test calls Random.Next() to get the next int
Here's how
int i = Math.Abs(386792);
while(i >= 10)
i /= 10;
and i will contain what you need
Try this
public int GetFirstDigit(int number) {
if ( number < 10 ) {
return number;
}
return GetFirstDigit ( (number - (number % 10)) / 10);
}
EDIT
Several people have requested the loop version
public static int GetFirstDigitLoop(int number)
{
while (number >= 10)
{
number = (number - (number % 10)) / 10;
}
return number;
}
The best I can come up with is:
int numberOfDigits = Convert.ToInt32(Math.Floor( Math.Log10( value ) ) );
int firstDigit = value / Math.Pow( 10, numberOfDigits );
variation on Anton's answer:
// cut down the number of divisions (assuming i is positive & 32 bits)
if (i >= 100000000) i /= 100000000;
if (i >= 10000) i /= 10000;
if (i >= 100) i /= 100;
if (i >= 10) i /= 10;
int myNumber = 8383;
char firstDigit = myNumber.ToString()[0];
// char = '8'
Had the same idea as Lennaert
int start = number == 0 ? 0 : number / (int) Math.Pow(10,Math.Floor(Math.Log10(Math.Abs(number))));
This also works with negative numbers.
If you think Keltex's answer is ugly, try this one, it's REALLY ugly, and even faster.
It does unrolled binary search to determine the length.
... leading code along the same lines
/* i<10000 */
if (i >= 100){
if (i >= 1000){
return i/1000;
}
else /* i<1000 */{
return i/100;
}
}
else /* i<100*/ {
if (i >= 10){
return i/10;
}
else /* i<10 */{
return i;
}
}
P.S. MartinStettner had the same idea.
Very simple (and probably quite fast because it only involves comparisons and one division):
if(i<10)
firstdigit = i;
else if (i<100)
firstdigit = i/10;
else if (i<1000)
firstdigit = i/100;
else if (i<10000)
firstdigit = i/1000;
else if (i<100000)
firstdigit = i/10000;
else (etc... all the way up to 1000000000)
An obvious, but slow, mathematical approach is:
int firstDigit = (int)(i / Math.Pow(10, (int)Math.Log10(i))));
int temp = i;
while (temp >= 10)
{
temp /= 10;
}
Result in temp
I know it's not C#, but it's surprising curious that in python the "get the first char of the string representation of the number" is the faster!
EDIT: no, I made a mistake, I forgot to construct again the int, sorry. The unrolled version it's the fastest.
$ cat first_digit.py
def loop(n):
while n >= 10:
n /= 10
return n
def unrolled(n):
while n >= 100000000: # yea... unlimited size int supported :)
n /= 100000000
if n >= 10000:
n /= 10000
if n >= 100:
n /= 100
if n >= 10:
n /= 10
return n
def string(n):
return int(str(n)[0])
$ python -mtimeit -s 'from first_digit import loop as test' \
'for n in xrange(0, 100000000, 1000): test(n)'
10 loops, best of 3: 275 msec per loop
$ python -mtimeit -s 'from first_digit import unrolled as test' \
'for n in xrange(0, 100000000, 1000): test(n)'
10 loops, best of 3: 149 msec per loop
$ python -mtimeit -s 'from first_digit import string as test' \
'for n in xrange(0, 100000000, 1000): test(n)'
10 loops, best of 3: 284 msec per loop
$
I just stumbled upon this old question and felt inclined to propose another suggestion since none of the other answers so far returns the correct result for all possible input values and it can still be made faster:
public static int GetFirstDigit( int i )
{
if( i < 0 && ( i = -i ) < 0 ) return 2;
return ( i < 100 ) ? ( i < 1 ) ? 0 : ( i < 10 )
? i : i / 10 : ( i < 1000000 ) ? ( i < 10000 )
? ( i < 1000 ) ? i / 100 : i / 1000 : ( i < 100000 )
? i / 10000 : i / 100000 : ( i < 100000000 )
? ( i < 10000000 ) ? i / 1000000 : i / 10000000
: ( i < 1000000000 ) ? i / 100000000 : i / 1000000000;
}
This works for all signed integer values inclusive -2147483648 which is the smallest signed integer and doesn't have a positive counterpart. Math.Abs( -2147483648 ) triggers a System.OverflowException and - -2147483648 computes to -2147483648.
The implementation can be seen as a combination of the advantages of the two fastest implementations so far. It uses a binary search and avoids superfluous divisions. A quick benchmark with the index of a loop with 100,000,000 iterations shows that it is twice as fast as the currently fastest implementation.
It finishes after 2,829,581 ticks.
For comparison I also measured a corrected variant of the currently fastest implementation which took 5,664,627 ticks.
public static int GetFirstDigitX( int i )
{
if( i < 0 && ( i = -i ) < 0 ) return 2;
if( i >= 100000000 ) i /= 100000000;
if( i >= 10000 ) i /= 10000;
if( i >= 100 ) i /= 100;
if( i >= 10 ) i /= 10;
return i;
}
The accepted answer with the same correction needed 16,561,929 ticks for this test on my computer.
public static int GetFirstDigitY( int i )
{
if( i < 0 && ( i = -i ) < 0 ) return 2;
while( i >= 10 )
i /= 10;
return i;
}
Simple functions like these can easily be proven for correctness since iterating all possible integer values takes not much more than a few seconds on current hardware. This means that it is less important to implement them in a exceptionally readable fashion as there simply won't ever be the need to fix a bug inside them later on.
Did some tests with one of my co-workers here, and found out most of the solutions don't work for numbers under 0.
public int GetFirstDigit(int number)
{
number = Math.Abs(number); <- makes sure you really get the digit!
if (number < 10)
{
return number;
}
return GetFirstDigit((number - (number % 10)) / 10);
}
Using all the examples below to get this code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace Benfords
{
class Program
{
static int FirstDigit1(int value)
{
return Convert.ToInt32(value.ToString().Substring(0, 1));
}
static int FirstDigit2(int value)
{
while (value >= 10) value /= 10;
return value;
}
static int FirstDigit3(int value)
{
return (int)(value.ToString()[0]) - 48;
}
static int FirstDigit4(int value)
{
return (int)(value / Math.Pow(10, (int)Math.Floor(Math.Log10(value))));
}
static int FirstDigit5(int value)
{
if (value < 10) return value;
if (value < 100) return value / 10;
if (value < 1000) return value / 100;
if (value < 10000) return value / 1000;
if (value < 100000) return value / 10000;
if (value < 1000000) return value / 100000;
if (value < 10000000) return value / 1000000;
if (value < 100000000) return value / 10000000;
if (value < 1000000000) return value / 100000000;
return value / 1000000000;
}
static int FirstDigit6(int value)
{
if (value >= 100000000) value /= 100000000;
if (value >= 10000) value /= 10000;
if (value >= 100) value /= 100;
if (value >= 10) value /= 10;
return value;
}
const int mcTests = 1000000;
static void Main(string[] args)
{
Stopwatch lswWatch = new Stopwatch();
Random lrRandom = new Random();
int liCounter;
lswWatch.Start();
for (liCounter = 0; liCounter < mcTests; liCounter++)
FirstDigit1(lrRandom.Next());
lswWatch.Stop();
Console.WriteLine("Test {0} = {1} ticks", 1, lswWatch.ElapsedTicks);
lswWatch.Reset();
lswWatch.Start();
for (liCounter = 0; liCounter < mcTests; liCounter++)
FirstDigit2(lrRandom.Next());
lswWatch.Stop();
Console.WriteLine("Test {0} = {1} ticks", 2, lswWatch.ElapsedTicks);
lswWatch.Reset();
lswWatch.Start();
for (liCounter = 0; liCounter < mcTests; liCounter++)
FirstDigit3(lrRandom.Next());
lswWatch.Stop();
Console.WriteLine("Test {0} = {1} ticks", 3, lswWatch.ElapsedTicks);
lswWatch.Reset();
lswWatch.Start();
for (liCounter = 0; liCounter < mcTests; liCounter++)
FirstDigit4(lrRandom.Next());
lswWatch.Stop();
Console.WriteLine("Test {0} = {1} ticks", 4, lswWatch.ElapsedTicks);
lswWatch.Reset();
lswWatch.Start();
for (liCounter = 0; liCounter < mcTests; liCounter++)
FirstDigit5(lrRandom.Next());
lswWatch.Stop();
Console.WriteLine("Test {0} = {1} ticks", 5, lswWatch.ElapsedTicks);
lswWatch.Reset();
lswWatch.Start();
for (liCounter = 0; liCounter < mcTests; liCounter++)
FirstDigit6(lrRandom.Next());
lswWatch.Stop();
Console.WriteLine("Test {0} = {1} ticks", 6, lswWatch.ElapsedTicks);
Console.ReadLine();
}
}
}
I get these results on an AMD Ahtlon 64 X2 Dual Core 4200+ (2.2 GHz):
Test 1 = 2352048 ticks
Test 2 = 614550 ticks
Test 3 = 1354784 ticks
Test 4 = 844519 ticks
Test 5 = 150021 ticks
Test 6 = 192303 ticks
But get these on a AMD FX 8350 Eight Core (4.00 GHz)
Test 1 = 3917354 ticks
Test 2 = 811727 ticks
Test 3 = 2187388 ticks
Test 4 = 1790292 ticks
Test 5 = 241150 ticks
Test 6 = 227738 ticks
So whether or not method 5 or 6 is faster depends on the CPU, I can only surmise this is because the branch prediction in the command processor of the CPU is smarter on the new processor, but I'm not really sure.
I dont have any Intel CPUs, maybe someone could test it for us?
Check this one too:
int get1digit(Int64 myVal)
{
string q12 = myVal.ToString()[0].ToString();
int i = int.Parse(q12);
return i;
}
Also good if you want multiple numbers:
int get3digit(Int64 myVal) //Int64 or whatever numerical data you have
{
char mg1 = myVal.ToString()[0];
char mg2 = myVal.ToString()[1];
char mg3 = myVal.ToString()[2];
char[] chars = { mg1, mg2, mg3 };
string q12= new string(chars);
int i = int.Parse(q12);
return i;
}
while (i > 10)
{
i = (Int32)Math.Floor((Decimal)i / 10);
}
// i is now the first int
Non iterative formula:
public static int GetHighestDigit(int num)
{
if (num <= 0)
return 0;
return (int)((double)num / Math.Pow(10f, Math.Floor(Math.Log10(num))));
}
Just to give you an alternative, you could repeatedly divide the integer by 10, and then rollback one value once you reach zero. Since string operations are generally slow, this may be faster than string manipulation, but is by no means elegant.
Something like this:
while(curr>=10)
curr /= 10;
start = getFirstDigit(start);
public int getFirstDigit(final int start){
int number = Math.abs(start);
while(number > 10){
number /= 10;
}
return number;
}
or
public int getFirstDigit(final int start){
return getFirstDigit(Math.abs(start), true);
}
private int getFirstDigit(final int start, final boolean recurse){
if(start < 10){
return start;
}
return getFirstDigit(start / 10, recurse);
}
int start = curr;
while (start >= 10)
start /= 10;
This is more efficient than a ToString() approach which internally must implement a similar loop and has to construct (and parse) a string object on the way ...
Very easy method to get the Last digit:
int myInt = 1821;
int lastDigit = myInt - ((myInt/10)*10); // 1821 - 1820 = 1
int i = 4567789;
int digit1 = int.Parse(i.ToString()[0].ToString());
This is what I usually do ,please refer my function below :
This function can extract first number occurance from any string you can modify and use this function according to your usage
public static int GetFirstNumber(this string strInsput)
{
int number = 0;
string strNumber = "";
bool bIsContNo = true;
bool bNoOccued = false;
try
{
var arry = strInsput.ToCharArray(0, strInsput.Length - 1);
foreach (char item in arry)
{
if (char.IsNumber(item))
{
strNumber = strNumber + item.ToString();
bIsContNo = true;
bNoOccued = true;
}
else
{
bIsContNo = false;
}
if (bNoOccued && !bIsContNo)
{
break;
}
}
number = Convert.ToInt32(strNumber);
}
catch (Exception ex)
{
return 0;
}
return number;
}
public static int GetFirstDigit(int n, bool removeSign = true)
{
if (removeSign)
return n <= -10 || n >= 10 ? Math.Abs(n) % 10 : Math.Abs(n);
else
return n <= -10 || n >= 10 ? n % 10 : n;
}
//Your code goes here
int[] test = new int[] { -1574, -221, 1246, -4, 8, 38546};
foreach(int n in test)
Console.WriteLine(string.Format("{0} : {1}", n, GetFirstDigit(n)));
Output:
-1574 : 4
-221 : 1
1246 : 6
-4 : 4
8 : 8
38546 : 6
Here is a simpler way that does not involve looping
int number = 1234
int firstDigit = Math.Floor(number/(Math.Pow(10, number.ToString().length - 1))
That would give us 1234/Math.Pow(10, 4 - 1) = 1234/1000 = 1

Categories

Resources