Related
Lets N be a number (10<=N<=10^5).
I have to break it into 3 numbers (x,y,z) such that it validates the following conditions.
1. x<=y<=z
2. x^2+y^2=z^2-1;
3. x+y+z<=N
I have to find how many combinations I can get from the given numbers in a method.
I have tried as follows but it's taking so much time for a higher number and resulting in a timeout..
int N= Int32.Parse(Console.ReadLine());
List<String> res = new List<string>();
//x<=y<=z
int mxSqrt = N - 2;
int a = 0, b = 0;
for (int z = 1; z <= mxSqrt; z++)
{
a = z * z;
for (int y = 1; y <= z; y++)
{
b = y * y;
for (int x = 1; x <= y; x++)
{
int x1 = b + x * x;
int y1 = a - 1;
if (x1 == y1 && ((x + y + z) <= N))
{
res.Add(x + "," + y + "," + z);
}
}
}
}
Console.WriteLine(res.Count());
My question:
My solution is taking time for a bigger number (I think it's the
for loops), how can I improve it?
Is there any better approach for the same?
Here's a method that enumerates the triples, rather than exhaustively testing for them, using number theory as described here: https://mathoverflow.net/questions/29644/enumerating-ways-to-decompose-an-integer-into-the-sum-of-two-squares
Since the math took me a while to comprehend and a while to implement (gathering some code that's credited above it), and since I don't feel much of an authority on the subject, I'll leave it for the reader to research. This is based on expressing numbers as Gaussian integer conjugates. (a + bi)*(a - bi) = a^2 + b^2. We first factor the number, z^2 - 1, into primes, decompose the primes into Gaussian conjugates and find different expressions that we expand and simplify to get a + bi, which can be then raised, a^2 + b^2.
A perk of reading about the Sum of Squares Function is discovering that we can rule out any candidate z^2 - 1 that contains a prime of form 4k + 3 with an odd power. Using that check alone, I was able to reduce Prune's loop on 10^5 from 214 seconds to 19 seconds (on repl.it) using the Rosetta prime factoring code below.
The implementation here is just a demonstration. It does not have handling or optimisation for limiting x and y. Rather, it just enumerates as it goes. Play with it here.
Python code:
# https://math.stackexchange.com/questions/5877/efficiently-finding-two-squares-which-sum-to-a-prime
def mods(a, n):
if n <= 0:
return "negative modulus"
a = a % n
if (2 * a > n):
a -= n
return a
def powmods(a, r, n):
out = 1
while r > 0:
if (r % 2) == 1:
r -= 1
out = mods(out * a, n)
r /= 2
a = mods(a * a, n)
return out
def quos(a, n):
if n <= 0:
return "negative modulus"
return (a - mods(a, n))/n
def grem(w, z):
# remainder in Gaussian integers when dividing w by z
(w0, w1) = w
(z0, z1) = z
n = z0 * z0 + z1 * z1
if n == 0:
return "division by zero"
u0 = quos(w0 * z0 + w1 * z1, n)
u1 = quos(w1 * z0 - w0 * z1, n)
return(w0 - z0 * u0 + z1 * u1,
w1 - z0 * u1 - z1 * u0)
def ggcd(w, z):
while z != (0,0):
w, z = z, grem(w, z)
return w
def root4(p):
# 4th root of 1 modulo p
if p <= 1:
return "too small"
if (p % 4) != 1:
return "not congruent to 1"
k = p/4
j = 2
while True:
a = powmods(j, k, p)
b = mods(a * a, p)
if b == -1:
return a
if b != 1:
return "not prime"
j += 1
def sq2(p):
if p % 4 != 1:
return "not congruent to 1 modulo 4"
a = root4(p)
return ggcd((p,0),(a,1))
# https://rosettacode.org/wiki/Prime_decomposition#Python:_Using_floating_point
from math import floor, sqrt
def fac(n):
step = lambda x: 1 + (x<<2) - ((x>>1)<<1)
maxq = long(floor(sqrt(n)))
d = 1
q = n % 2 == 0 and 2 or 3
while q <= maxq and n % q != 0:
q = step(d)
d += 1
return q <= maxq and [q] + fac(n//q) or [n]
# My code...
# An answer for https://stackoverflow.com/questions/54110614/
from collections import Counter
from itertools import product
from sympy import I, expand, Add
def valid(ps):
for (p, e) in ps.items():
if (p % 4 == 3) and (e & 1):
return False
return True
def get_sq2(p, e):
if p == 2:
if e & 1:
return [2**(e / 2), 2**(e / 2)]
else:
return [2**(e / 2), 0]
elif p % 4 == 3:
return [p, 0]
else:
a,b = sq2(p)
return [abs(a), abs(b)]
def get_terms(cs, e):
if e == 1:
return [Add(cs[0], cs[1] * I)]
res = [Add(cs[0], cs[1] * I)**e]
for t in xrange(1, e / 2 + 1):
res.append(
Add(cs[0] + cs[1]*I)**(e-t) * Add(cs[0] - cs[1]*I)**t)
return res
def get_lists(ps):
items = ps.items()
lists = []
for (p, e) in items:
if p == 2:
a,b = get_sq2(2, e)
lists.append([Add(a, b*I)])
elif p % 4 == 3:
a,b = get_sq2(p, e)
lists.append([Add(a, b*I)**(e / 2)])
else:
lists.append(get_terms(get_sq2(p, e), e))
return lists
def f(n):
for z in xrange(2, n / 2):
zz = (z + 1) * (z - 1)
ps = Counter(fac(zz))
is_valid = valid(ps)
if is_valid:
print "valid (does not contain a prime of form\n4k + 3 with an odd power)"
print "z: %s, primes: %s" % (z, dict(ps))
lists = get_lists(ps)
cartesian = product(*lists)
for element in cartesian:
print "prime square decomposition: %s" % list(element)
p = 1
for item in element:
p *= item
print "complex conjugates: %s" % p
vals = p.expand(complex=True, evaluate=True).as_coefficients_dict().values()
x, y = vals[0], vals[1] if len(vals) > 1 else 0
print "x, y, z: %s, %s, %s" % (x, y, z)
print "x^2 + y^2, z^2-1: %s, %s" % (x**2 + y**2, z**2 - 1)
print ''
if __name__ == "__main__":
print f(100)
Output:
valid (does not contain a prime of form
4k + 3 with an odd power)
z: 3, primes: {2: 3}
prime square decomposition: [2 + 2*I]
complex conjugates: 2 + 2*I
x, y, z: 2, 2, 3
x^2 + y^2, z^2-1: 8, 8
valid (does not contain a prime of form
4k + 3 with an odd power)
z: 9, primes: {2: 4, 5: 1}
prime square decomposition: [4, 2 + I]
complex conjugates: 8 + 4*I
x, y, z: 8, 4, 9
x^2 + y^2, z^2-1: 80, 80
valid (does not contain a prime of form
4k + 3 with an odd power)
z: 17, primes: {2: 5, 3: 2}
prime square decomposition: [4 + 4*I, 3]
complex conjugates: 12 + 12*I
x, y, z: 12, 12, 17
x^2 + y^2, z^2-1: 288, 288
valid (does not contain a prime of form
4k + 3 with an odd power)
z: 19, primes: {2: 3, 3: 2, 5: 1}
prime square decomposition: [2 + 2*I, 3, 2 + I]
complex conjugates: (2 + I)*(6 + 6*I)
x, y, z: 6, 18, 19
x^2 + y^2, z^2-1: 360, 360
valid (does not contain a prime of form
4k + 3 with an odd power)
z: 33, primes: {17: 1, 2: 6}
prime square decomposition: [4 + I, 8]
complex conjugates: 32 + 8*I
x, y, z: 32, 8, 33
x^2 + y^2, z^2-1: 1088, 1088
valid (does not contain a prime of form
4k + 3 with an odd power)
z: 35, primes: {17: 1, 2: 3, 3: 2}
prime square decomposition: [4 + I, 2 + 2*I, 3]
complex conjugates: 3*(2 + 2*I)*(4 + I)
x, y, z: 18, 30, 35
x^2 + y^2, z^2-1: 1224, 1224
Here is a simple improvement in Python (converting to the faster equivalent in C-based code is left as an exercise for the reader). To get accurate timing for the computation, I removed printing the solutions themselves (after validating them in a previous run).
Use an outer loop for one free variable (I chose z), constrained only by its relation to N.
Use an inner loop (I chose y) constrained by the outer loop index.
The third variable is directly computed per requirement 2.
Timing results:
-------------------- 10
1 solutions found in 2.3365020751953125e-05 sec.
-------------------- 100
6 solutions found in 0.00040078163146972656 sec.
-------------------- 1000
55 solutions found in 0.030081748962402344 sec.
-------------------- 10000
543 solutions found in 2.2078349590301514 sec.
-------------------- 100000
5512 solutions found in 214.93411707878113 sec.
That's 3:35 for the large case, plus your time to collate and/or print the results.
If you need faster code (this is still pretty brute-force), look into Diophantine equations and parameterizations to generate (y, x) pairs, given the target value of z^2 - 1.
import math
import time
def break3(N):
"""
10 <= N <= 10^5
return x, y, z triples such that:
x <= y <= z
x^2 + y^2 = z^2 - 1
x + y + z <= N
"""
"""
Observations:
z <= x + y
z < N/2
"""
count = 0
z_limit = N // 2
for z in range(3, z_limit):
# Since y >= x, there's a lower bound on y
target = z*z - 1
ymin = int(math.sqrt(target/2))
for y in range(ymin, z):
# Given y and z, compute x.
# That's a solution iff x is integer.
x_target = target - y*y
x = int(math.sqrt(x_target))
if x*x == x_target and x+y+z <= N:
# print("solution", x, y, z)
count += 1
return count
test = [10, 100, 1000, 10**4, 10**5]
border = "-"*20
for case in test:
print(border, case)
start = time.time()
print(break3(case), "solutions found in", time.time() - start, "sec.")
The bounds of x and y are an important part of the problem. I personally went with this Wolfram Alpha query and checked the exact forms of the variables.
Thanks to #Bleep-Bloop and comments, a very elegant bound optimization was found, which is x < n and x <= y < n - x. The results are the same and the times are nearly identical.
Also, since the only possible values for x and y are positive even integers, we can reduce the amount of loop iterations by half.
To optimize even further, since we compute the upper bound of x, we build a list of all possible values for x and make the computation parallel. That saves a massive amount of time on higher values of N but it's a bit slower for smaller values because of the overhead of the parallelization.
Here's the final code:
Non-parallel version, with int values:
List<string> res = new List<string>();
int n2 = n * n;
double maxX = 0.5 * (2.0 * n - Math.Sqrt(2) * Math.Sqrt(n2 + 1));
for (int x = 2; x < maxX; x += 2)
{
int maxY = (int)Math.Floor((n2 - 2.0 * n * x - 1.0) / (2.0 * n - 2.0 * x));
for (int y = x; y <= maxY; y += 2)
{
int z2 = x * x + y * y + 1;
int z = (int)Math.Sqrt(z2);
if (z * z == z2 && x + y + z <= n)
res.Add(x + "," + y + "," + z);
}
}
Parallel version, with long values:
using System.Linq;
...
// Use ConcurrentBag for thread safety
ConcurrentBag<string> res = new ConcurrentBag<string>();
long n2 = n * n;
double maxX = 0.5 * (2.0 * n - Math.Sqrt(2) * Math.Sqrt(n2 + 1L));
// Build list to parallelize
int nbX = Convert.ToInt32(maxX);
List<int> xList = new List<int>();
for (int x = 2; x < maxX; x += 2)
xList.Add(x);
Parallel.ForEach(xList, x =>
{
int maxY = (int)Math.Floor((n2 - 2.0 * n * x - 1.0) / (2.0 * n - 2.0 * x));
for (long y = x; y <= maxY; y += 2)
{
long z2 = x * x + y * y + 1L;
long z = (long)Math.Sqrt(z2);
if (z * z == z2 && x + y + z <= n)
res.Add(x + "," + y + "," + z);
}
});
When ran individually on a i5-8400 CPU, I get these results:
N: 10; Solutions: 1;
Time elapsed: 0.03 ms (Not parallel, int)
N: 100; Solutions: 6;
Time elapsed: 0.05 ms (Not parallel, int)
N: 1000; Solutions: 55;
Time elapsed: 0.3 ms (Not parallel, int)
N: 10000; Solutions: 543;
Time elapsed: 13.1 ms (Not parallel, int)
N: 100000; Solutions: 5512;
Time elapsed: 849.4 ms (Parallel, long)
You must use long when N is greater than 36340, because when it's squared, it overflows an int's max value. Finally, the parallel version starts to get better than the simple one when N is around 23000, with ints.
No time to properly test it, but seemed to yield the same results as your code (at 100 -> 6 results and at 1000 -> 55 results).
With N=1000 a time of 2ms vs your 144ms also without List
and N=10000 a time of 28ms
var N = 1000;
var c = 0;
for (int x = 2; x < N; x+=2)
{
for (int y = x; y < (N - x); y+=2)
{
long z2 = x * x + y * y + 1;
int z = (int) Math.Sqrt(z2);
if (x + y + z > N)
break;
if (z * z == z2)
c++;
}
}
Console.WriteLine(c);
#include<iostream>
#include<math.h>
int main()
{
int N = 10000;
int c = 0;
for (int x = 2; x < N; x+=2)
{
for (int y = x; y < (N - x); y+=2)
{
auto z = sqrt(x * x + y * y + 1);
if(x+y+z>N){
break;
}
if (z - (int) z == 0)
{
c++;
}
}
}
std::cout<<c;
}
This is my solution. On testing the previous solutions for this problem I found that x,y are always even and z is odd. I dont know the mathematical nature behind this, I am currently trying to figure that out.
I want to get it done in C# and it should be covering all the test
cases based on condition provided in the question.
The basic code, converted to long to process the N <= 100000 upper limit, with every optimizaion thrown in I could. I used alternate forms from #Mat's (+1) Wolfram Alpha query to precompute as much as possible. I also did a minimal perfect square test to avoid millions of sqrt() calls at the upper limit:
public static void Main()
{
int c = 0;
long N = long.Parse(Console.ReadLine());
long N_squared = N * N;
double half_N_squared = N_squared / 2.0 - 0.5;
double x_limit = N - Math.Sqrt(2) / 2.0 * Math.Sqrt(N_squared + 1);
for (long x = 2; x < x_limit; x += 2)
{
long x_squared = x * x + 1;
double y_limit = (half_N_squared - N * x) / (N - x);
for (long y = x; y < y_limit; y += 2)
{
long z_squared = x_squared + y * y;
int digit = (int) z_squared % 10;
if (digit == 3 || digit == 7)
{
continue; // minimalist non-perfect square elimination
}
long z = (long) Math.Sqrt(z_squared);
if (z * z == z_squared)
{
c++;
}
}
}
Console.WriteLine(c);
}
I followed the trend and left out "the degenerate solution" as implied by the OP's code but not explicitly stated.
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
I'm trying to calculate the cumulative binomial probability of 'n' trials, with 'p' probability and 'r' as the successful outcome of each trial. I have written the following code that works sometimes, but not always:
Console.WriteLine ();
Console.WriteLine ("B~(n, p)");
incorrectN:
Console.WriteLine ("Enter value of 'n': ");
int n = Convert.ToInt32 (Console.ReadLine ());
if (n < 0) {
Console.WriteLine ("ERROR: 'n' must be greater than 0");
goto incorrectN;
}
incorrectP:
Console.WriteLine ();
Console.WriteLine ("Enter value of 'p': ");
double p = Convert.ToDouble (Console.ReadLine ());
if (p > 1) {
Console.WriteLine ();
Console.WriteLine ("ERROR: 'p' must be between 0 and 1");
goto incorrectP;
}
Console.WriteLine ();
incorrectS:
int r = GetR();
int k = r;
double binomTotal = 0;
for (int j = r + 1; j > 0; j--) {
int nCr = Factorial(n) / (Factorial(n - (r - k)) * Factorial(r - k));
binomTotal = binomTotal + nCr * Math.Pow(p, (r - k)) * Math.Pow(1 - p, (n - (r - k)));
k--;
}
Console.WriteLine();
Console.WriteLine(binomTotal);
P.S. I have written the GetR() and Factorial() functions elsewhere within the class, where GetR() asks the user for the value of 'r' and Factorial() is defined as follows:
public static int Factorial(int x)
{
return x <= 1 ? 1 : x * Factorial(x - 1);
}
I tested the code with values n = 10, p = 0.5 and r = 5 and the output is 0.623046875, which is correct. However, when I use n = 13, p = 0.35 and r = 7, I get 0.297403640622647 instead of 0.9538.
Any help would be much appreciated.
In addition to your own answer:
public static double Factorial(double x)
{
return x <= 1 ? 1 : x * Factorial(x - 1);
}
accepts a double parameter, which means that x is not restricted to be an integer.
So you could call your Factorial method like this.
var fac1 = Factorial(1.4);
var fac2 = Factorial(2.7);
However, this does not make sense since the factorial is defined only* for , meaning that
is undefined.
So, instead of using double and allowing for invalid inputs, you should be using long instead, which has a greater range than int.
public static long Factorial(long x)
{
return x <= 1 ? 1 : x * Factorial(x - 1);
}
* there are some cases where factorials can be used with real values as well - e.g. by using the gamma function - but I don't think they're relevant to your use case and therefore you should not allow invalid parameters.
Change:
public static int Factorial(int x)
{
return x <= 1 ? 1 : x * Factorial(x - 1);
}
To:
public static double Factorial(double x)
{
return x <= 1 ? 1 : x * Factorial(x - 1);
}
Because Factorial(13) is too large for Int32.
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);
I am trying to make a program that calculates the answer of a quadratic equation with the general formula but i am encountering a few errors.
The way I have my Windows Form Application set up it asks for a, b, and c, and substitutes them in the general formula.
I have 3 text boxes, one for each value of a, b and c and one more for the answer, and it is supposed to work with a button I called "calculate".
My problem is that when I try something other than a perfect trinomial square, the answer comes up as NaN.
Here is some of the code I have:
private void textBox1_TextChanged(object sender, EventArgs e)
{
a = Double.Parse(textBox1.Text);
}
^ This is how I am assigning values to the variables
double sqrtpart = b * b - 4 * a * c;
answer = (b + Math.Sqrt(sqrtpart)) / 2 * a;
textBox4.Text = answer.ToString();
group 2a and make sure values are valid (b^2 > 4ac)
answer = (b + Math.Sqrt(sqrtpart)) / (2 * a);
First, make sure that 4ac < b². The quadratic formula also utilizes the ± sign, so we must make two separate variables to hold the two different answers.
double sqrtpart = (b * b) - (4 * a * c);
answer1 = ((-1)*b + Math.Sqrt(sqrtpart)) / (2 * a);
answer2 = ((-1)*b - Math.Sqrt(sqrtpart)) / (2 * a);
textBox4.Text = answer1.ToString() + " and " + answer2.ToString();
If you want your calculator to be able to compute complex numbers try the following
string ans = "";
double root1 = 0;
double root2 = 0;
double b = 0;
double a = 0;
double c = 0;
double identifier = 0;
a =Convert.ToDouble(Console.ReadLine());
b = Convert.ToDouble(Console.ReadLine());
c = Convert.ToDouble(Console.ReadLine());
identifier = b * b - (4 * a * c);
if (identifier > 0)
{
root1 = (-b+(Math.Sqrt(identifier)/(2*a)));
root2 = (-b - (Math.Sqrt(identifier) / (2 * a)));
string r1 = Convert.ToString(root1);
string r2 = Convert.ToString(root2);
ans = "Root1 =" + r1 + "Root2 = " + r2;
Console.WriteLine(ans);
}
if (identifier < 0)
{
double Real = (-b / (2 * a));
double Complex = ((Math.Sqrt((identifier*(-1.00))) / (2 * a)));
string SReal = Convert.ToString(Real);
string SComplex = Convert.ToString(Complex);
ans = "Roots = " + SReal + "+/-" + SComplex + "i";
Console.WriteLine(ans);
}
if (identifier == 0)
{
root1 = (-b / (2 * a));
string Root = Convert.ToString(root1);
ans = "Repeated roots : " + Root;
}
Use the following code:
using System;
using System.Collections.Generic;
using System.Text;
namespace SoftwareAndFinance
{
class Math
{
// quadratic equation is a second order of polynomial equation in a single variable
// x = [ -b +/- sqrt(b^2 - 4ac) ] / 2a
public static void SolveQuadratic(double a, double b, double c)
{
double sqrtpart = b * b - 4 * a * c;
double x, x1, x2, img;
if (sqrtpart > 0)
{
x1 = (-b + System.Math.Sqrt(sqrtpart)) / (2 * a);
x2 = (-b - System.Math.Sqrt(sqrtpart)) / (2 * a);
Console.WriteLine("Two Real Solutions: {0,8:f4} or {1,8:f4}", x1, x2);
}
else if (sqrtpart < 0)
{
sqrtpart = -sqrtpart;
x = -b / (2 * a);
img = System.Math.Sqrt(sqrtpart) / (2 * a);
Console.WriteLine("Two Imaginary Solutions: {0,8:f4} + {1,8:f4} i or {2,8:f4} + {3,8:f4} i", x, img, x, img);
}
else
{
x = (-b + System.Math.Sqrt(sqrtpart)) / (2 * a);
Console.WriteLine("One Real Solution: {0,8:f4}", x);
}
}
static void Main(string[] args)
{
// 6x^2 + 11x - 35 = 0
SolveQuadratic(6, 11, -35);
// 5x^2 + 6x + 1 = 0
SolveQuadratic(5, 6, 1);
// 2x^2 + 4x + 2 = 0
SolveQuadratic(2, 4, 2);
// 5x^2 + 2x + 1 = 0
SolveQuadratic(5, 2, 1);
}
}
}
Here is the original source.
A little late, but here is my solution:
using System;
using System.Collections.Generic;
namespace MyFunctions
{
class Program
{
static void Main(string[] args)
{
printABCSolution(1, -3, 4);
printABCSolution(1, -4, 4);
printABCSolution(1, -5, 4);
printABCSolution(9, 30, 25);
printABCSolution(9, -15, 25);
Console.ReadKey();
}
private static void printABCSolution(double a, double b, double c)
{
Console.WriteLine($"Solution a={a} b={b} c={c}");
var solution = ABCMath.ABCFormula(a, b, c);
Console.WriteLine($"# Solutions found: {solution.Count}");
solution.ForEach(x => Console.WriteLine($"x={x}"));
}
}
public static class ABCMath
{
public static List<double> ABCFormula(double a, double b, double c)
{
// Local formula
double formula(int plusOrMinus, double d) => (-b + (plusOrMinus * Math.Sqrt(d))) / (2 * a);
double discriminant = b * b - 4 * a * c;
List<double> result = new List<double>();
if (discriminant >= 0)
{
result.Add(formula(1, discriminant));
if (discriminant > 0)
result.Add(formula(-1, discriminant));
}
return result;
}
}
}
Output:
Solution a=1 b=-3 c=4
# Solutions found: 0
Solution a=1 b=-4 c=4
# Solutions found: 1
x=2
Solution a=1 b=-5 c=4
# Solutions found: 2
x=4
x=1
Solution a=9 b=30 c=25
# Solutions found: 1
x=-1,66666666666667
Solution a=9 b=-15 c=25
# Solutions found: 0
Here is code:
using System;
namespace RoomPaintCost
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("This program applies quadratic formula to Ax^2+Bx+C=0 problems");
double[] ABC= getABC();
double[] answerArray=QuadFormula(ABC);
Console.WriteLine("Positive answer: {0:0.000} \n Negative answer: {1:0.000}", answerArray[0], answerArray[1]);
}
//Form of Ax^2 + Bx + C
//Takes array of double containing A,B,C
//Returns array of positive and negative result
public static double[] QuadFormula(double[] abc)
{
NotFiniteNumberException e = new NotFiniteNumberException();
try
{
double a = abc[0];
double b = abc[1];
double c = abc[2];
double discriminant = ((b * b) - (4 * a * c));
if (discriminant < 0.00)
{
throw e;
}
discriminant = (Math.Sqrt(discriminant));
Console.WriteLine("discriminant: {0}",discriminant);
double posAnswer = ((-b + discriminant) / (2 * a));
double negAnswer = ((-b - discriminant) / (2 * a));
double[] xArray= { posAnswer,negAnswer};
return xArray;
}
catch (NotFiniteNumberException)
{
Console.WriteLine("Both answers will be imaginary numbers");
double[] xArray = { Math.Sqrt(-1), Math.Sqrt(-1) };
return xArray;
}
}
public static double[] getABC()
{
Console.Write("A=");
string sA = Console.ReadLine();
Console.Write("B=");
string sB = Console.ReadLine();
Console.Write("C=");
string sC = Console.ReadLine();
int intA = Int32.Parse(sA);
int intB = Int32.Parse(sB);
int intC = Int32.Parse(sC);
double[] ABC = { intA, intB, intC };
return ABC;
}
}
}