I am new to C language :)
Although the code runs perfectly, I cannot understand how it is operating. I mean let's take (k = i / j * j) as an example, according to mathematic rules the answer should be k = 2 but the program output is 0. can anyone help me out with what rule C language is applying to it?
int i = 2, j=3, k,l;
float a, b;
k = i / j * j;
l = j / i * i;
a = i / j * j;
b = j / i * i;
printf( "%d %d %f %f", k, l, a, b );
According to the operator precedence of the C language, the corresponding operation is performed as follows.
k = i / j * j;
= (i / j) * j;
= (2 / 3) * 3
= 0 * 3
= 0
Note: https://en.cppreference.com/w/c/language/operator_precedence
(As you probably know, division between Integers cannot represent a decimal point as an operation.)
Related
I've been trying to do this but I'm getting an error Time Limit Exceeded, please help!
Example of input and exepected output
Input#1: 5 2
Output#1: 2 1
#include<stdio.h>
int main(){
long long n, k, p, r;
scanf("%lld %lld", &n, &k);
if (r >= 0 && r < k){
if (n >= 1){
p = (n - r) / k;
r = n / (p * k);
}
}
printf("%lld %lld", p, r);
return 0;
}
Here you can take the reference from the code written in python, I first calculate the highest multiple of k (less than k) divisible by n. It is calculated by the // operator in python. Like, 37/5=7.4 but 37//4 gives 7 (floor of 7.4). Then I calculate r and finally prints them
# 37 = p*5 + r
# take n=37 and k=5
n,k = map(int,input().split()) # take n,k as input
p = n//k # it will max multiple of k divisible by n
r = n - (p*k) # r = 37 - (7*5)
print("p =",p," and r=",r) # print answer here
The variable r is not initialized and has an indeterminate value
long long n, k, p, r;
So this if statement
if (r >= 0 && r < k){
at once invokes undefined behavior.
What you need is to include the header
#include <stdlib.h>
and to use the function lldiv declared in this header that calculates the quotient and the remainder of two numbers.
Here is a demonstration program.
#include <stdlib.h>
#include <stdio.h>
int main( void )
{
long long int n = 100, k = 13;
lldiv_t result = lldiv( n, k );
long long int p = result.quot;
long long int r = result.rem;
printf( "p = %lld, r = %lld\n", p, r );
}
The program output is
p = 7, r = 9
Or instead of the function you could use the two operators / and % like
p = n / k;
r = n % k;
I use gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
The c code is:
// Compile with:
// gcc -o little_c little.c
#include <stdio.h> // printf
void main(void) {
int n = 800;
float a[n][n], b[n][n], c[n][n];
int i, j, k;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
a[i][j] = (float) (i+j);
b[i][j] = (float) (i-j);
}
}
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
float t = (float) 0.0;
for (k = 0; k < n; k++)
t += a[i][k] * a[i][k] + b[k][j] * b[k][j];
//t += a[i][k] + b[k][j]; // If I comment the above line and uncomment this, the c and fortran reults are the same
c[i][j] = t;
}
}
printf("%f", c[n-1][n-1]); // prints the very last element
}
Fortran code:
! Compile with:
! gfortran -o little_fort little.f90
program little
implicit none
integer, parameter :: n = 800
real :: a(n,n), b(n,n), c(n,n)
real :: t
integer :: i, j, k ! Counters
do i = 1, n
do j = 1, n
a(i,j) = real(i-1+j-1) ! Minus one, for it to be like the c version
b(i,j) = real(i-1-(j-1)) ! because in c, the index goes from 0 to n-1
end do
end do
do i = 1, n
do j = 1, n
t = 0.0
do k = 1, n
t = t + a(i,k) * a(i,k) + b(k,j) * b(k,j)
!t = t + a(i,k) + b(k,j) ! If I comment the above line and uncomment this, the c and fortran reults are the same
end do
c(i,j) = t
end do
end do
write (*,"(F20.4)") c(n,n) ! This is the same as c[n-1][n-1] in c
end program little
The c program prints: 1362136192.000000
and the Fortran program prints: 1362137216.0000
If I do not multiply each element by itself, as I state in the comments in the code, I get the same value for both versions of the program:
c prigram: 639200.000000
Fortran program: 639200.0000
Why when I use a multiplication the c and Fortran code produce different results?. Does it have to be with different implementations of the real numbers?
The difference is due to the order of evaluation combined with the limited precision of the floating point type.
If you change the Fortran version to
t = t + (a(i,k) * a(i,k) + b(k,j) * b(k,j))
i.e. add parenthesis around the terms with a and b, you get the same result for both languages. The C version already uses this order of evaluation due to the use of the += assignment operator.
As mentioned in the comments, this is expected behavior at the limits of the available precision.
When I wrote an Ada version of the program I found that I had to reduce the decimal precision to 6 decimals to achieve the Fortran answer.
The Ada version is:
with Ada.Text_IO; use Ada.Text_Io;
procedure Main is
type Real is digits 6;
package Real_IO is new Ada.Text_IO.Float_IO(Real);
use Real_IO;
subtype Index is integer range 1..800;
type Matrix is array(Index, Index) of Real;
A : Matrix;
B : Matrix;
C : Matrix;
T : Real := 0.0;
begin
for I in Index loop
for J in Index loop
A(I,J) := Real(I - 1 + J - 1);
B(I,J) := Real(I - 1 - (J - 1));
end loop;
end loop;
for I in Index loop
for J in Index loop
T := 0.0;
for K in Index loop
T := T + A(I,K) * A(I,K) + B(K,J) *B(K,J);
end loop;
C(I,J) := T;
end loop;
end loop;
Put(Item => C(Index'Last, Index'Last), Exp => 0, Aft => 4);
New_Line;
end Main;
The line defining type Real defines the precision of the floating point type:
type Real is digits 6;
The value produced using six digits of precision is
1362137216.0000
Use of higher precision floating point types resulted in the value
1362135200.0000
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm trying to write a Haskell program that calculates multiples. Basically, when given two integers a and b, I want to find how many integers 1 ≤ bi ≤ b are multiple of any integer 2 ≤ ai ≤ a. For example, if a = 3 and b = 30, I want to know how many integers in the range of 1-30 are a multiple of 2 or 3; there are 20 such integers: 2, 3, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 22, 24, 26, 27, 28, 30.
I have a C program that does this. I'm trying to get this translated into Haskell, but part of the difficulty is getting around the loops that I've used since Haskell doesn't use loops. I appreciate any and all help in translating this!
My C program for reference (sorry if formatting is off):
#define PRIME_RANGE 130
#define PRIME_CNT 32
#define UPPER_LIMIT (1000000000000000ull) //10^15
#define MAX_BASE_MULTIPLES_COUNT 25000000
typedef struct
{
char primeFactorFlag;
long long multiple;
}multipleInfo;
unsigned char primeFlag[PRIME_RANGE + 1];
int primes[PRIME_CNT];
int primeCnt = 0;
int maxPrimeStart[PRIME_CNT];
multipleInfo baseMultiples[MAX_BASE_MULTIPLES_COUNT];
multipleInfo mergedMultiples[MAX_BASE_MULTIPLES_COUNT];
int baseMultiplesCount, mergedMultiplesCount;
void findOddMultiples(int a, long long b, long long *count);
void generateBaseMultiples(void);
void mergeLists(multipleInfo listSource[], int countS, multipleInfo
listDest[], int *countD);
void sieve(void);
int main(void)
{
int i, j, a, n, startInd, endInd;
long long b, multiples;
//Generate primes
sieve();
primes[primeCnt] = PRIME_RANGE + 1;
generateBaseMultiples();
baseMultiples[baseMultiplesCount].multiple = UPPER_LIMIT + 1;
//Input and Output
scanf("%d", &n);
for(i = 1; i <= n; i++)
{
scanf("%d%lld", &a, &b);
//If b <= a, all are multiple except 1
if(b <= a)
printf("%lld\n",b-1);
else
{
//Add all even multiples
multiples = b / 2;
//Add all odd multiples
findOddMultiples(a, b, &multiples);-
printf("%lld\n", multiples);
}
}
return 0;
}
void findOddMultiples(int a, long long b, long long *count)
{
int i, k;
long long currentNum;
for(k = 1; k < primeCnt && primes[k] <= a; k++)
{
for(i = maxPrimeStart[k]; i < maxPrimeStart[k + 1] &&
baseMultiples[i].multiple <= b; i++)
{
currentNum = b/baseMultiples[i].multiple;
currentNum = (currentNum + 1) >> 1; // remove even multiples
if(baseMultiples[i].primeFactorFlag) //odd number of factors
(*count) += currentNum;
else
(*count) -= currentNum;
}
}
}
void addTheMultiple(long long value, int primeFactorFlag)
{
baseMultiples[baseMultiplesCount].multiple = value;
baseMultiples[baseMultiplesCount].primeFactorFlag = primeFactorFlag;
baseMultiplesCount++;
}
void generateBaseMultiples(void)
{
int i, j, t, prevCount;
long long curValue;
addTheMultiple(3, 1);
mergedMultiples[0] = baseMultiples[0];
mergedMultiplesCount = 1;
maxPrimeStart[1] = 0;
prevCount = mergedMultiplesCount;
for(i = 2; i < primeCnt; i++)
{
maxPrimeStart[i] = baseMultiplesCount;
addTheMultiple(primes[i], 1);
for(j = 0; j < prevCount; j++)
{
curValue = mergedMultiples[j].multiple * primes[i];
if(curValue > UPPER_LIMIT)
break;
addTheMultiple(curValue, 1 - mergedMultiples[j].primeFactorFlag);
}
if(i < primeCnt - 1)
mergeLists(&baseMultiples[prevCount], baseMultiplesCount - prevCount, mergedMultiples, &mergedMultiplesCount);
prevCount = mergedMultiplesCount;
}
maxPrimeStart[primeCnt] = baseMultiplesCount;
}
void mergeLists(multipleInfo listSource[], int countS, multipleInfo listDest[], int *countD)
{
int limit = countS + *countD;
int i1, i2, j, k;
//Copy one list in unused safe memory
for(j = limit - 1, k = *countD - 1; k >= 0; j--, k--)
listDest[j] = listDest[k];
//Merge the lists
for(i1 = 0, i2 = countS, k = 0; i1 < countS && i2 < limit; k++)
{
if(listSource[i1].multiple <= listDest[i2].multiple)
listDest[k] = listSource[i1++];
else
listDest[k] = listDest[i2++];
}
while(i1 < countS)
listDest[k++] = listSource[i1++];
while(i2 < limit)
listDest[k++] = listDest[i2++];
*countD = k;
}
void sieve(void)
{
int i, j, root = sqrt(PRIME_RANGE);
primes[primeCnt++] = 2;
for(i = 3; i <= PRIME_RANGE; i+= 2)
{
if(!primeFlag[i])
{
primes[primeCnt++] = i;
if(root >= i)
{
for(j = i * i; j <= PRIME_RANGE; j += i << 1)
primeFlag[j] = 1;
}
}
}
}
First, unless I'm grossly misunderstanding, the number of multiples you have there is wrong. The number of multiples of 2 between 1 and 30 is 15, and the number of multiples of 3 between 1 and 30 is 10, so there should be 25 numbers there.
EDIT: I did misunderstand; you want unique multiples.
To get unique multiples, you can use Data.Set, which has the invariant that the elements of the Set are unique and ordered ascendingly.
If you know you aren't going to exceed x = maxBound :: Int, you can get even better speedups using Data.IntSet. I've also included some test cases and annotated with comments what they run at on my machine.
{-# LANGUAGE BangPatterns #-}
{-# OPTIONS_GHC -O2 #-}
module Main (main) where
import System.CPUTime (getCPUTime)
import Data.IntSet (IntSet)
import qualified Data.IntSet as IntSet
main :: IO ()
main = do
test 3 30 -- 0.12 ms
test 131 132 -- 0.14 ms
test 500 300000 -- 117.63 ms
test :: Int -> Int -> IO ()
test !a !b = do
start <- getCPUTime
print (numMultiples a b)
end <- getCPUTime
print $ "Needed " ++ show ((fromIntegral (end - start)) / 10^9) ++ " ms.\n"
numMultiples :: Int -> Int -> Int
numMultiples !a !b = IntSet.size (foldMap go [2..a])
where
go :: Int -> IntSet
go !x = IntSet.fromAscList [x, x+x .. b]
I'm not really into understanding your C, so I implemented a solution afresh using the algorithm discussed here. The N in the linked algorithm is the product of the primes up to a in your problem description.
So first we'll need a list of primes. There's a standardish trick for getting a list of primes that is at once very idiomatic and relatively efficient:
primes :: [Integer]
primes = 2:filter isPrime [3..]
-- Doesn't work right for n<2, but we never call it there, so who cares?
isPrime :: Integer -> Bool
isPrime n = go primes n where
go (p:ps) n | p*p>n = True
| otherwise = n `rem` p /= 0 && go ps n
Next up: we want a way to iterate over the positive square-free divisors of N. This can be achieved by iterating over the subsets of the primes less than a. There's a standard idiomatic way to get a powerset, namely:
-- import Control.Monad
-- powerSet :: [a] -> [[a]]
-- powerSet = filterM (const [False, True])
That would be a fine component to use, but since at the end of the day we only care about the product of each powerset element and the value of the Mobius function of that product, we would end up duplicating a lot of multiplications and counting problems. It's cheaper to compute those two things directly while producing the powerset. So:
-- Given the prime factorization of a square-free number, produce a list of
-- its divisors d together with mu(d).
divisorsWithMu :: Num a => [a] -> [(a, a)]
divisorsWithMu [] = [(1, 1)]
divisorsWithMu (p:ps) = rec ++ [(p*d, -mu) | (d, mu) <- rec] where
rec = divisorsWithMu ps
With that in hand, we can just iterate and do a little arithmetic.
f :: Integer -> Integer -> Integer
f a b = b - sum
[ mu * (b `div` d)
| (d, mu) <- divisorsWithMu (takeWhile (<=a) primes)
]
And that's all the code. Crunched 137 lines of C down to 15 lines of Haskell -- not bad! Try it out in ghci:
> f 3 30
20
As an additional optimization, one could consider modifying divisorsWithMu to short-circuit when its divisor is bigger than b, as we know such terms will not contribute to the final sum. This makes a noticeable difference for large a, as without it there are exponentially many elements in the powerset. Here's how that modification looks:
-- Given an upper bound and the prime factorization of a square-free number,
-- produce a list of its divisors d that are no larger than the upper bound
-- together with mu(d).
divisorsWithMuUnder :: (Ord a, Num a) => a -> [a] -> [(a, a)]
divisorsWithMuUnder n [] = [(1, 1)]
divisorsWithMuUnder n (p:ps) = rec ++ [(p*d, -mu) | (d, mu) <- rec, p*d<=n]
where rec = divisorsWithMuUnder n ps
f' :: Integer -> Integer -> Integer
f' a b = b - sum
[ mu * (b `div` d)
| (d, mu) <- divisorsWithMuUnder b (takeWhile (<=a) primes)
]
Not much more complicated; the only really interesting difference is that there's now a condition in the list comprehension. Here's an example of f' finishing quickly for inputs that would take infeasibly long with f:
> f' 100 100000
88169
With data-ordlist package mentioned by Daniel Wagner in the comments, it is just
f a b = length $ unionAll [ [p,p+p..b] | p <- takeWhile (<= a) primes]
That is all. Some timings, for non-compiled code run inside GHCi:
~> f 100 (10^5)
88169
(0.05 secs, 48855072 bytes)
~> f 131 (3*10^6)
2659571
(0.55 secs, 1493586480 bytes)
~> f 131 132
131
(0.00 secs, 0 bytes)
~> f 500 300000
274055
(0.11 secs, 192704760 bytes)
Compiling will surely make the memory consumption a non-issue, by converting the length to a counting loop.
You'll have to use recursion in place of loops.
In (most) procedural or object-orientated languages, you should hardly ever (never?) be using recursion. It is horribly inefficient, as a new stack frame must be created each time the recursive function is called.
However, in a functional language, like Haskell, the compiler is often able to optimize the recursion away into a loop, which makes it much faster then its procedural counterparts.
I've converted your sieve function into a set of recursive functions in C. I'll leave it to you to convert it into Haskell:
int main(void) {
//...
int root = sqrt(PRIME_RANGE);
primes[primeCnt++] = 2;
sieve(3, PRIME_RANGE, root);
//...
}
void sieve(int i, int end, int root) {
if(i > end) {
return;
}
if(!primeFlag[i]) {
primes[primeCnt++] = i;
if(root >= i) {
markMultiples(i * i, PRIME_RANGE, i);
}
}
i += 2;
sieve(i, end, root);
}
void markMultiples(int j, int end, int prime) {
if(j > end) {
return;
}
primeFlag[j] = 1;
j += i << 1;
markMultiples(j, end, prime);
}
The point of recursion is that the same function is called repeatedly, until a condition is met. The results of one recursive call are passed onto the next call, until the condition is met.
Also, why are you bit-fiddling instead of just multiplying or dividing by 2? Any half-decent compiler these days can convert most multiplications and divisions by 2 into a bit-shift.
I have been using Ubuntu 12.04 LTS with GCC to compile my the codes for my assignment for a while. However, recently I have run into two issues as follows:
The following code calculates zero for a nonzero value with the second formula is used.
There is a large amount of error in the calculation of the integral of the standard normal distribution from 0 to 5 or larger standard deviations.
How can I remedy these issues? I am especially obsessed with the first one. Any help or suggestion is appreciated. thanks in advance.
The code is as follows:
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <stdlib.h>
#define N 599
long double
factorial(long double n)
{
//Here s is the free parameter which is increased by one in each step and
//pro is the initial product and by setting pro to be 0 we also cover the
//case of zero factorial.
int s = 1;
long double pro = 1;
//Here pro stands for product.
if (n < 0)
printf("Factorial is not defined for a negative number \n");
else {
while (n >= s) {
pro *= s;
s++;
}
return pro;
}
}
int main()
{
// Since the function given is the standard normal distribution
// probability density function we have mean = 0 and variance = 1.
// Hence we also have z = x; while dealing with only positive values of
// x and keeping in mind that the PDF is symmetric around the mean.
long double * summand1 = malloc(N * sizeof(long double));
long double * summand2 = malloc(N * sizeof(long double));
int p = 0, k, z[5] = {0, 3, 5, 10, 20};
long double sum1[5] = {0}, sum2[5] = {0} , factor = 1.0;
for (p = 0; p <= 4; p++)
{
for (k = 0; k <= N; k++)
{
summand1[k] = (1 / sqrtl(M_PI * 2) )* powl(-1, k) * powl(z[p], 2 * k + 1) / ( factorial(k) * (2 * k + 1) * powl(2, k));
sum1[p] += summand1[k];
}
//Wolfamalpha site gives the same value here
for (k = 0; k <= N; k++)
{
factor *= (2 * k + 1);
summand2[k] = ((1 / sqrtl(M_PI * 2) ) * powl(z[p], 2 * k + 1) / factor);
//printf("%Le \n", factor);
sum2[p] += summand2[k];
}
sum2[p] = sum2[p] * expl((-powl(z[p],2)) / 2);
}
for (p = 0; p < 4; p++)
{
printf("The sum obtained for z between %d - %d \
\nusing the first formula is %Lf \n", z[p], z[p+1], sum1[p+1]);
printf("The sum obtained for z between %d - %d \
\nusing the second formula is %Lf \n", z[p], z[p+1], sum2[p+1]);
}
return 0;
}
The working code without the outermost for loop is
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <stdlib.h>
#define N 1200
long double
factorial(long double n)
{
//Here s is the free parameter which is increased by one in each step and
//pro is the initial product and by setting pro to be 0 we also cover the
//case of zero factorial.
int s = 1;
long double pro = 1;
//Here pro stands for product.
if (n < 0)
printf("Factorial is not defined for a negative number \n");
else {
while (n >= s) {
pro *= s;
s++;
}
return pro;
}
}
int main()
{
// Since the function given is the standard normal distribution
// probability density function we have mean = 0 and variance = 1.
// Hence we also have z = x; while dealing with only positive values of
// x and keeping in mind that the PDF is symmetric around the mean.
long double * summand1 = malloc(N * sizeof(long double));
long double * summand2 = malloc(N * sizeof(long double));
int k, z = 3;
long double sum1 = 0, sum2 = 0, pro = 1.0;
for (k = 0; k <= N; k++)
{
summand1[k] = (1 / sqrtl(M_PI * 2) )* powl(-1, k) * powl(z, 2 * k + 1) / ( factorial(k) * (2 * k + 1) * powl(2, k));
sum1 += summand1[k];
}
//Wolfamalpha site gives the same value here
printf("The sum obtained for z between 0-3 using the first formula is %Lf \n", sum1);
for (k = 0; k <= N; k++)
{
pro *= (2 * k + 1);
summand2[k] = ((1 / sqrtl(M_PI * 2) * powl(z, 2 * k + 1) / pro));
//printf("%Le \n", pro);
sum2 += summand2[k];
}
sum2 = sum2 * expl((-powl(z,2)) / 2);
printf("The sum obtained for z between 0-3 using the second formula is %Lf \n", sum2);
return 0;
}
I'm quite certain that the problem is in factor not being set back to 1 in the outer loop..
factor *= (2 * k + 1); (in the loop that calculates sum2.)
In the second version provided the one that works it starts with z=3
However in the first loop since you do not clear it between iterations on p by the time you reach z[2] it already is a huge number.
EDIT: Possible help with precision..
Basically you have a huge number powl(z[p], 2 * k + 1) divided by another huge number factor. huge floating point numbers lose their precision. The way to avoid that is to perform the division as soon as possible..
Instead of first calculating powl(z[p], 2 * k + 1) and dividing by factor :
- (z[p]z[p] ... . * z[p]) / (1*3*5*...(2*k+1))`
rearrange the calculation: (z[p]/1) * (z[p]^2/3) * (z[p]^2/5) ... (z[p]^2/(2*k+1))
You can do this in sumand2 calculation and a similar trick in summand1
for (i = 0; i < n; i++)
{
x[i] = (float) (i * step);
k = 5;
sum = 0;
while(k > 0)
{
sum = sum + (1/k) * sin((k*PI*x[i])/5);
k = k - 2;
}
y1[i] = (4/PI)*sum;
y2[i] = 0*(4/PI)*sin((PI*x[i])/5);
}
When debugging for each value of k other than 1 the sum shows as being equal to 0, am I implementing the loop correctly?
EDIT 1:
int k;
double sum;
Since both 1 and k are ints -- 1/k is integer division, its always going to be 0 if k > 1. Therefore nothing is added to sum. You want 1/k to perform floating point division. Try 1.0 / k instead of 1/k.
1/k will give 0. Since it is Integer Division.
You will have to give 1.0/k or 1/(float)k