bash: How to round/floor/ceiling non-decimals thousands number? - bash

lets say I have this number here 100675
how to turn it into 101000
all the solution I have found on google are solving decimals number.

The bash shell is able to do calculations internally, such as with the following transcript:
pax:~> for x in 100675 100499 100500 100999 101000; do
...:~> ((y = (x + 500) / 1000 * 1000))
...:~> echo " $x becomes $y"
...:~> done
100675 becomes 101000
100499 becomes 100000
100500 becomes 101000
100999 becomes 101000
101000 becomes 101000
This statement, ((y = (x + 500) / 1000 * 1000)), first adds 500 to make the otherwise-truncating integer division by 1,000 into a rounding division, then re-multiplies it by 1,000.

This is a bit of a weird function, but here goes a rough version that might be what you need. At least this could be a starting point.
# in:
# $1 - the number to round
# $2 - the 10 power to round at. Defaults to 3 (i.e. 1000)
# output:
# The rounded number
roundPow()
{
local n="$1"
local pow="${2:-3}"
local div="$((10 ** pow))"
echo "$((((n + div / 2) / div) * div))"
}
This is very rough around the edges, it's not validating parameters, etc, but should give you a baseline.
Hope this helps.

Related

Fastest way to determine how many times a number can be sutracted in a total number, while each subtraction result is greater then another number

Is it possible to solve the following problem without a cycle? By using a math formula. It could make my app much faster.
How many times can 43920 be subtracted in 189503, while each subtraction result is greater than 79920
Example:
189503 > 79920 so 189503-43920=145583 (1 time)
145583 > 79920 so 145583-43920=101663 (2 times)
101663 > 79920 so 101663-43920=57743 (3 times)
57743 < 43920 so it means it ran 3 times
This would be the same as 189503-(43920*3) = 57743 or 189503 % (43920*3)
I don't know if i wrote my question well, maybe you can help
Yes. It resumes to: Math.floor((189503 - 79920) / 43920). Which equals 2.
First subtract 79920 to keep only the distance that you really care.
Divide the remainder by 43920. This will result in the "exact" number of times it can be subtracted.
Finally, apply a floor function to get an integer number.
Let x = the number of times you need to subtract by
189503 - (43920 * x) = 79920
189503 = 79920 + (43920 * x)
189503 - 79920 = 43920x
x = (189503 - 79920) / 43920
x = 2.49505919854
Given that you can not really subtract something any other than a whole number (integer) of times the answer is 2.

Different output from round function of oracle and Pandas data frame [duplicate]

I am facing a strange behavior of the round() function:
for i in range(1, 15, 2):
n = i / 2
print(n, "=>", round(n))
This code prints:
0.5 => 0
1.5 => 2
2.5 => 2
3.5 => 4
4.5 => 4
5.5 => 6
6.5 => 6
I expected the floating values to be always rounded up, but instead, it is rounded to the nearest even number.
Why such behavior, and what is the best way to get the correct result?
I tried to use the fractions but the result is the same.
The Numeric Types section documents this behaviour explicitly:
round(x[, n])
x rounded to n digits, rounding half to even. If n is omitted, it defaults to 0.
Note the rounding half to even. This is also called bankers rounding; instead of always rounding up or down (compounding rounding errors), by rounding to the nearest even number you average out rounding errors.
If you need more control over the rounding behaviour, use the decimal module, which lets you specify exactly what rounding strategy should be used.
For example, to round up from half:
>>> from decimal import localcontext, Decimal, ROUND_HALF_UP
>>> with localcontext() as ctx:
... ctx.rounding = ROUND_HALF_UP
... for i in range(1, 15, 2):
... n = Decimal(i) / 2
... print(n, '=>', n.to_integral_value())
...
0.5 => 1
1.5 => 2
2.5 => 3
3.5 => 4
4.5 => 5
5.5 => 6
6.5 => 7
For example:
from decimal import Decimal, ROUND_HALF_UP
Decimal(1.5).quantize(0, ROUND_HALF_UP)
# This also works for rounding to the integer part:
Decimal(1.5).to_integral_value(rounding=ROUND_HALF_UP)
You can use this:
import math
def normal_round(n):
if n - math.floor(n) < 0.5:
return math.floor(n)
return math.ceil(n)
It will round number up or down properly.
round() will round either up or down, depending on if the number is even or odd. A simple way to only round up is:
int(num + 0.5)
If you want this to work properly for negative numbers use:
((num > 0) - (num < 0)) * int(abs(num) + 0.5)
Note, this can mess up for large numbers or really precise numbers like 5000000000000001.0 and 0.49999999999999994.
Love the fedor2612 answer. I expanded it with an optional "decimals" argument for those who want to use this function to round any number of decimals (say for example if you want to round a currency $26.455 to $26.46).
import math
def normal_round(n, decimals=0):
expoN = n * 10 ** decimals
if abs(expoN) - abs(math.floor(expoN)) < 0.5:
return math.floor(expoN) / 10 ** decimals
return math.ceil(expoN) / 10 ** decimals
oldRounding = round(26.455,2)
newRounding = normal_round(26.455,2)
print(oldRounding)
print(newRounding)
Output:
26.45
26.46
The behavior you are seeing is typical IEEE 754 rounding behavior. If it has to choose between two numbers that are equally different from the input, it always picks the even one. The advantage of this behavior is that the average rounding effect is zero - equally many numbers round up and down. If you round the half way numbers in a consistent direction the rounding will affect the expected value.
The behavior you are seeing is correct if the objective is fair rounding, but that is not always what is needed.
One trick to get the type of rounding you want is to add 0.5 and then take the floor. For example, adding 0.5 to 2.5 gives 3, with floor 3.
Why make it so complicated? (Only works for positive numbers)
def HalfRoundUp(value):
return int(value + 0.5)
You could of course make it into a lambda which would be:
HalfRoundUp = lambda value: int(value + 0.5)
Unfortunately, this simple answer doesn't work with negative numbers, but it can be fixed with the floor function from math: (This works for both positive and negative numbers too)
from math import floor
def HalfRoundUp(value):
floor(value + 0.5)
Short version: use the decimal module. It can represent numbers like 2.675 precisely, unlike Python floats where 2.675 is really 2.67499999999999982236431605997495353221893310546875 (exactly). And you can specify the rounding you desire: ROUND_CEILING, ROUND_DOWN, ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_UP, and ROUND_05UP are all options.
In the question this is basically an issue when dividing a positive integer by 2. The easisest way is int(n + 0.5) for individual numbers.
However we cannot apply this to series, therefore what we then can do for example for a pandas dataframe, and without going into loops, is:
import numpy as np
df['rounded_division'] = np.where(df['some_integer'] % 2 == 0, round(df['some_integer']/2,0), round((df['some_integer']+1)/2,0))
A small addition as the rounding half up with some of the solutions might not work as expected in some cases.
Using the function from above for instance:
from decimal import Decimal, ROUND_HALF_UP
def round_half_up(x: float, num_decimals: int) -> float:
if num_decimals < 0:
raise ValueError("Num decimals needs to be at least 0.")
target_precision = "1." + "0" * num_decimals
rounded_x = float(Decimal(x).quantize(Decimal(target_precision), ROUND_HALF_UP))
return rounded_x
round_half_up(1.35, 1)
1.4
round_half_up(4.35, 1)
4.3
Where I was expecting 4.4. What did the trick for me was converting x into a string first.
from decimal import Decimal, ROUND_HALF_UP
def round_half_up(x: float, num_decimals: int) -> float:
if num_decimals < 0:
raise ValueError("Num decimals needs to be at least 0.")
target_precision = "1." + "0" * num_decimals
rounded_x = float(Decimal(str(x)).quantize(Decimal(target_precision), ROUND_HALF_UP))
return rounded_x
round_half_up(4.35, 1)
4.4
Rounding to the nearest even number has become common practice in numerical disciplines. "Rounding up" produces a slight bias towards larger results.
So, from the perspective of the scientific establishment, round has the correct behavior.
Here is another solution.
It will work as normal rounding in excel.
from decimal import Decimal, getcontext, ROUND_HALF_UP
round_context = getcontext()
round_context.rounding = ROUND_HALF_UP
def c_round(x, digits, precision=5):
tmp = round(Decimal(x), precision)
return float(tmp.__round__(digits))
c_round(0.15, 1) -> 0.2, c_round(0.5, 0) -> 1
The following solution achieved "school fashion rounding" without using the decimal module (which turns out to be slow).
def school_round(a_in,n_in):
''' python uses "banking round; while this round 0.05 up" '''
if (a_in * 10 ** (n_in + 1)) % 10 == 5:
return round(a_in + 1 / 10 ** (n_in + 1), n_in)
else:
return round(a_in, n_in)
e.g.
print(round(0.005,2)) # 0
print(school_round(0.005,2)) #0.01
So just to make sure there is a crystal clear working example here, I wrote a small convenience function
def round_half_up(x: float, num_decimals: int) -> float:
"""Use explicit ROUND HALF UP. See references, for an explanation.
This is the proper way to round, as taught in school.
Args:
x:
num_decimals:
Returns:
https://stackoverflow.com/questions/33019698/how-to-properly-round-up-half-float-numbers-in-python
"""
if num_decimals < 0:
raise ValueError("Num decimals needs to be at least 0.")
target_precision = "1." + "0" * num_decimals
rounded_x = float(Decimal(x).quantize(Decimal(target_precision), ROUND_HALF_UP))
return rounded_x
And an appropriate set of test cases
def test_round_half_up():
x = 1.5
y = round_half_up(x, 0)
assert y == 2.0
y = round_half_up(x, 1)
assert y == 1.5
x = 1.25
y = round_half_up(x, 1)
assert y == 1.3
y = round_half_up(x, 2)
assert y == 1.25
This is a function that takes the number of decimal places as an argument.
It also rounds up half decimal.
import math
def normal_round(n, decimal_places):
if int((str(n)[-1])) < 5:
return round(n, decimal_places)
return round(n + 10**(-1 * (decimal_places+1)), decimal_places)
Test cases:
>>> normal_round(5.12465, 4)
5.1247
>>> normal_round(5.12464, 4)
5.1246
>>> normal_round(5.12467, 4)
5.1247
>>> normal_round(5.12463, 4)
5.1246
>>> normal_round(5.1241, 4)
5.1241
>>> normal_round(5.1248, 4)
5.1248
>>> normal_round(5.1248, 3)
5.125
>>> normal_round(5.1242, 3)
5.124
You can use:
from decimal import Decimal, ROUND_HALF_UP
for i in range(1, 15, 2):
n = i / 2
print(n, "=>", Decimal(str(n)).quantize(Decimal("1"), rounding=ROUND_HALF_UP))
A classical mathematical rounding without any libraries
def rd(x,y=0):
''' A classical mathematical rounding by Voznica '''
m = int('1'+'0'*y) # multiplier - how many positions to the right
q = x*m # shift to the right by multiplier
c = int(q) # new number
i = int( (q-c)*10 ) # indicator number on the right
if i >= 5:
c += 1
return c/m
Compare:
print( round(0.49), round(0.51), round(0.5), round(1.5), round(2.5), round(0.15,1)) # 0 1 0 2 2 0.1
print( rd(0.49), rd(0.51), rd(0.5), rd(1.5), rd(2.5), rd(0.15,1)) # 0 1 1 2 3 0.2
Knowing that round(9.99,0) rounds to int=10 and int(9.99) rounds to int=9 brings success:
Goal: Provide lower and higher round number depending on value
def get_half_round_numers(self, value):
"""
Returns dict with upper_half_rn and lower_half_rn
:param value:
:return:
"""
hrns = {}
if not isinstance(value, float):
print("Error>Input is not a float. None return.")
return None
value = round(value,2)
whole = int(value) # Rounds 9.99 to 9
remainder = (value - whole) * 100
if remainder >= 51:
hrns['upper_half_rn'] = round(round(value,0),2) # Rounds 9.99 to 10
hrns['lower_half_rn'] = round(round(value,0) - 0.5,2)
else:
hrns['lower_half_rn'] = round(int(value),2)
hrns['upper_half_rn'] = round(int(value) + 0.5,2)
return hrns
Some testing:
yw
import math
# round tossing n digits from the end
def my_round(n, toss=1):
def normal_round(n):
if isinstance(n, int):
return n
intn, dec = str(n).split(".")
if int(dec[-1]) >= 5:
if len(dec) == 1:
return math.ceil(n)
else:
return float(intn + "." + str(int(dec[:-1]) + 1))
else:
return float(intn + "." + dec[:-1])
while toss >= 1:
n = normal_round(n)
toss -= 1
return n
for n in [1.25, 7.3576, 30.56]:
print(my_round(n, 2))
1.0
7.36
31
import math
def round_half_up(x: float) -> int:
if x < 0:
return math.trunc(x) if -x % 1 < 0.5 else math.floor(x)
else:
return math.trunc(x) if x % 1 < 0.5 else math.ceil(x)
This even works for corner cases like 0.49999999999999994 and 5000000000000001.0.
You can try this
def round(num):
return round(num + 10**(-9))
it will work since num = x.5 will always will be x.5 + 0.00...01 in the process which its closer to x+1 hence the round function will work properly and it will round x.5 to x+1

How to round float number with while loop in MATLAB?

I have a rather unorthodox homework assignment where I am to write a simple function where a double value is rounded to an integer with using only a while loop.
The main goal is to write something similar to the round function.
I made some progress where I should add or subtract a very small double value and I would eventually hit a number that will become an integer:
while(~isinteger(inumberup))
inumberup=inumberup+realmin('double');
end
However, this results in a never-ending loop. Is there a way to accomplish this task?
I'm not allowed to use round, ceil, floor, for, rem or mod for this question.
Assumption: if statements and the abs function are allowed as the list of forbidden functions does not include this.
Here's one solution. What you can do is keep subtracting the input value by 1 until you get to a point where it becomes less than 1. The number produced after this point is the fractional component of the number (i.e. if our number was 3.4, the fractional component is 0.4). You would then check to see if the fractional component, which we will call f, is less than 0.5. If it is, that means you need to round down and so you would subtract the input number with f. If the number is larger than 0.5 or equal to 0.5, you would add the input number by (1 - f) in order to go up to the next highest number. However, this only handles the case for positive values. For negative values, round in MATLAB rounds towards negative infinity, so what we ought to do is take the absolute value of the input number and do this subtraction to find the fractional part.
Once we do this, we then check to see what the fractional part is equal to, and then depending on the sign of the number, we either add or subtract accordingly. If the fractional part is less than 0.5 and if the number is positive, we need to subtract by f else we need to add by f. If the fractional part is greater than or equal to 0.5, if the number is positive we need to add by (1 - f), else we subtract by (1 - f)
Therefore, assuming that num is the input number of interest, you would do:
function out = round_hack(num)
%// Repeatedly subtract until we get a value that less than 1
%// i.e. the fractional part
%// Also make sure to take the absolute value
f = abs(num);
while f > 1
f = f - 1;
end
%// Case where we need to round down
if f < 0.5
if num > 0
out = num - f;
else
out = num + f;
end
%// Case where we need to round up
else
if num > 0
out = num + (1 - f);
else
out = num - (1 - f);
end
end
Be advised that this will be slow for larger values of num. I've also wrapped this into a function for ease of debugging. Here are a few example runs:
>> round_hack(29.1)
ans =
29
>> round_hack(29.6)
ans =
30
>> round_hack(3.4)
ans =
3
>> round_hack(3.5)
ans =
4
>> round_hack(-0.4)
ans =
0
>> round_hack(-0.6)
ans =
-1
>> round_hack(-29.7)
ans =
-30
You can check that this agrees with MATLAB's round function for the above test cases.
You can do it without loop: you can use num2str to convert the number into a string, then find the position of the . in the string and extract the string fron its beginning up to the position of the .; then you convert it back to a numebr with str2num
To round it you have to check the value of the first char (converted into a number) after the ..
r=rand*100
s=num2str(r)
idx=strfind(num2str(r),'.')
v=str2num(s(idx+1))
if(v <= 5)
rounded_val=str2num(s(1:idx-1))
else
rounded_val=str2num(s(1:idx-1))+1
end
Hope this helps.
Qapla'

Evaluating math Equations with Brackets

I am just trying to Convert secs back to hours n minutes for a day. However am hitting an error in the Minute Equation! its not evaluating the braces in the order! how can we evalvate math equations like the one I have below.
I want to divide the total_secs by 3600 and then multiply the result with 60 then Again find the modulus of the result with 60.
Here s my attempt
#!/bin/ksh
set -x
total_secs=3685;
hour=$(( (total_secs % 3600) ));
minute=$(( (((total_secs / 3600) * 60) % 60) ));
seconds=$(( (((total_secs / 3600) * (60) * (60)) % 60) ));
echo ""$hour":"$minute":"$seconds""
Thanks In advance
The ordering of operations wasn't what was causing the problem. According to this reference, the Korn shell has the same precedence and associativity as the C programming language, so multiplication, division and remainder happen from left to right. The correct maths would be:
#!/bin/ksh
total_secs=3685
hour=$(( total_secs / 3600 ))
minute=$(( total_secs / 60 % 60 )) # equivalent to (total_secs / 60) % 60
seconds=$(( total_secs % 60 ))
echo "$hour:$minute:$seconds"
# output 1:1:25
If you want to format the output, perhaps you could use printf
printf "%02d:%02d:%02d\n" $hour $minute $seconds
# output 01:01:25
edit: operator precedence
Basic arithmetic operations are carried out in the following order:
* / %
+ -
Multiple operations of the same precedence will be evaluated from left to right as they appear in the expression.
$(( ((x*y) / z) + n ))
is equivalent to either of the following:
$(( x * y / z + n ))
$(( n + x * y / z ))
because in both cases, the * is the highest precedence and nearest to the left of the expression. Second will be the / and finally the +.
There is no harm in inserting additional ( ) to make your intentions clear but remember that the whole expression must be enclosed within $(( )).

Code Golf: Leibniz formula for Pi

Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I recently posted one of my favourite interview whiteboard coding questions in "What's your more controversial programming opinion", which is to write a function that computes Pi using the Leibniz formula.
It can be approached in a number of different ways, and the exit condition takes a bit of thought, so I thought it might make an interesting code golf question. Shortest code wins!
Given that Pi can be estimated using the function 4 * (1 - 1/3 + 1/5 - 1/7 + ...) with more terms giving greater accuracy, write a function that calculates Pi to within 0.00001.
Edit: 3 Jan 2008
As suggested in the comments I changed the exit condition to be within 0.00001 as that's what I really meant (an accuracy 5 decimal places is much harder due to rounding and so I wouldn't want to ask that in an interview, whereas within 0.00001 is an easier to understand and implement exit condition).
Also, to answer the comments, I guess my intention was that the solution should compute the number of iterations, or check when it had done enough, but there's nothing to prevent you from pre-computing the number of iterations and using that number. I really asked the question out of interest to see what people would come up with.
J, 14 chars
4*-/%>:+:i.1e6
Explanation
1e6 is number 1 followed by 6 zeroes (1000000).
i.y generates the first y non negative numbers.
+: is a function that doubles each element in the list argument.
>: is a function that increments by one each element in the list argument.
So, the expression >:+:i.1e6 generates the first one million odd numbers:
1 3 5 7 ...
% is the reciprocal operator (numerator "1" can be omitted).
-/ does an alternate sum of each element in the list argument.
So, the expression -/%>:+:i.1e6 generates the alternate sum of the reciprocals of the first one million odd numbers:
1 - 1/3 + 1/5 - 1/7 + ...
4* is multiplication by four. If you multiply by four the previous sum, you have π.
That's it! J is a powerful language for mathematics.
Edit: since generating 9! (362880) terms for the alternate sum is sufficient to have 5 decimal digit accuracy, and since the Leibniz formula can be written also this way:
4 - 4/3 + 4/5 - 4/7 + ...
...you can write a shorter, 12 chars version of the program:
-/4%>:+:i.9!
Language: Brainfuck, Char count: 51/59
Does this count? =]
Because there are no floating-point numbers in Brainfuck, it was pretty difficult to get the divisions working properly. Grr.
Without newline (51):
+++++++[>+++++++<-]>++.-----.+++.+++.---.++++.++++.
With newline (59):
+++++++[>+++++++>+<<-]>++.-----.+++.+++.---.++++.++++.>+++.
Perl
26 chars
26 just the function, 27 to compute, 31 to print. From the comments to this answer.
sub _{$-++<1e6&&4/$-++-&_} # just the sub
sub _{$-++<1e6&&4/$-++-&_}_ # compute
sub _{$-++<1e6&&4/$-++-&_}say _ # print
28 chars
28 just computing, 34 to print. From the comments. Note that this version cannot use 'say'.
$.=.5;$\=2/$.++-$\for 1..1e6 # no print
$.=.5;$\=2/$.++-$\for$...1e6;print # do print, with bonus obfuscation
36 chars
36 just computing, 42 to print. Hudson's take at dreeves's rearrangement, from the comments.
$/++;$\+=8/$//($/+2),$/+=4for$/..1e6
$/++;$\+=8/$//($/+2),$/+=4for$/..1e6;print
About the iteration count: as far as my math memories go, 400000 is provably enough to be accurate to 0.00001. But a million (or as low as 8e5) actually makes the decimal expansion actually match 5 fractional places, and it's the same character count so I kept that.
Ruby, 33 characters
(0..1e6).inject{|a,b|2/(0.5-b)-a}
Another C# version:
(60 characters)
4*Enumerable.Range(0, 500000).Sum(x => Math.Pow(-1, x)/(2*x + 1)); // = 3,14159
52 chars in Python:
print 4*sum(((-1.)**i/(2*i+1)for i in xrange(5**8)))
(51 dropping the 'x' from xrange.)
36 chars in Octave (or Matlab):
l=0:5^8;disp((-1).^l*(4./(2.*l+1))')
(execute "format long;" to show all the significant digits.) Omitting 'disp' we reach 30 chars:
octave:5> l=0:5^8;(-1).^l*(4./(2.*l+1))'
ans = 3.14159009359631
Oracle SQL 73 chars
select -4*sum(power(-1,level)/(level*2-1)) from dual connect by level<1e6
Language: C, Char count: 71
float p;main(i){for(i=1;1E6/i>5;i+=2)p-=(i%4-2)*4./i;printf("%g\n",p);}
Language: C99, Char count: 97 (including required newline)
#include <stdio.h>
float p;int main(){for(int i=1;1E6/i>5;i+=2)p-=(i%4-2)*4./i;printf("%g\n",p);}
I should note that the above versions (which are the same) keep track of whether an extra iteration would affect the result at all. Thus, it performs a minimum number of operations. To add more digits, replace 1E6 with 1E(num_digits+1) or 4E5 with 4E(num_digits) (depending on the version). For the full programs, %g may need to be replaced. float may need to be changed to double as well.
Language: C, Char count: 67 (see notes)
double p,i=1;main(){for(;i<1E6;i+=4)p+=8/i/(i+2);printf("%g\n",p);}
This version uses a modified version of posted algorithm, as used by some other answers. Also, it is not as clean/efficient as the first two solutions, as it forces 100 000 iterations instead of detecting when iterations become meaningless.
Language: C, Char count: 24 (cheating)
main(){puts("3.14159");}
Doesn't work with digit counts > 6, though.
Haskell
I got it down to 34 characters:
foldl subtract 4$map(4/)[3,5..9^6]
This expression yields 3.141596416935556 when evaluated.
Edit: here's a somewhat shorter version (at 33 characters) that uses foldl1 instead of foldl:
foldl1 subtract$map(4/)[1,3..9^6]
Edit 2: 9^6 instead of 10^6. One has to be economical ;)
Edit 3: Replaced with foldl' and foldl1' with foldl and foldl1 respectively—as a result of Edit 2, it no longer overflows. Thanks to ShreevatsaR for noticing this.
23 chars in MATLAB:
a=1e6;sum(4./(1-a:4:a))
F#:
Attempt #1:
let pi = 3.14159
Cheating? No, its winning with style!
Attempt #2:
let pi =
seq { 0 .. 100 }
|> Seq.map (fun x -> float x)
|> Seq.fold (fun x y -> x + (Math.Pow(-1.0, y)/(2.0 * y + 1.0))) 0.0
|> (fun x -> x * 4.0)
Its not as compact as it could possibly get, but pretty idiomatic F#.
common lisp, 55 chars.
(loop for i from 1 upto 4e5 by 4 sum (/ 8d0 i (+ i 2)))
Mathematica, 27 chars (arguably as low as 26, or as high as 33)
NSum[8/i/(i+2),{i,1,9^9,4}]
If you remove the initial "N" then it returns the answer as a (huge) fraction.
If it's cheating that Mathematica doesn't need a print statement to output its result then prepend "Print#" for a total of 33 chars.
NB:
If it's cheating to hardcode the number of terms, then I don't think any answer has yet gotten this right. Checking when the current term is below some threshold is no better than hardcoding the number of terms. Just because the current term is only changing the 6th or 7th digit doesn't mean that the sum of enough subsequent terms won't change the 5th digit.
Using the formula for the error term in an alternating series (and thus the necessary number of iterations to achieve the desired accuracy is not hard coded into the program):
public static void Main(string[] args) {
double tolerance = 0.000001;
double piApproximation = LeibnizPi(tolerance);
Console.WriteLine(piApproximation);
}
private static double LeibnizPi(double tolerance) {
double quarterPiApproximation = 0;
int index = 1;
double term;
int sign = 1;
do {
term = 1.0 / (2 * index - 1);
quarterPiApproximation += ((double)sign) * term;
index++;
sign = -sign;
} while (term > tolerance);
return 4 * quarterPiApproximation;
}
C#:
public static double Pi()
{
double pi = 0;
double sign = 1;
for (int i = 1; i < 500002; i += 2)
{
pi += sign / i;
sign = -sign;
}
return 4 * pi;
}
Perl :
$i+=($_&1?4:-4)/($_*2-1)for 1..1e6;print$i
for a total of 42 chars.
Ruby, 41 chars (using irb):
s=0;(3..3e6).step(4){|i|s+=8.0/i/(i-2)};s
Or this slightly longer, non-irb version:
s=0;(3..3e6).step(4){|i|s+=8.0/i/(i-2)};p s
This is a modified Leibniz:
Combine pairs of terms. This gives you 2/3 + 2/35 + 2/99 + ...
Pi becomes 8 * (1/(1 * 3) + 1/(5 * 7) + 1/(9 * 11) + ...)
F# (Interactive Mode) (59 Chars)
{0.0..1E6}|>Seq.fold(fun a x->a+ -1.**x/(2.*x+1.))0.|>(*)4.
(Yields a warning but omits the casts)
Here's a solution in MUMPS.
pi(N)
N X,I
S X=1 F I=3:4:N-2 S X=X-(1/I)+(1/(I+2))
Q 4*X
Parameter N indicates how many repeated fractions to use. That is, if you pass in 5 it will evaluate 4 * (1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/11)
Some empirical testing showed that N=272241 is the lowest value that gives a correct value of 3.14159 when truncated to 5 decimal points. You have to go to N=852365 to get a value that rounds to 3.14159.
C# using iterator block:
static IEnumerable<double> Pi()
{
double i = 4, j = 1, k = 4;
for (;;)
{
yield return k;
k += (i *= -1) / (j += 2);
}
}
For the record, this Scheme implementation has 95 characters ignoring unnecessary whitespace.
(define (f)
(define (p a b)
(if (> a b)
0
(+ (/ 1.0 (* a (+ a 2))) (p (+ a 4) b))))
(* 8 (p 1 1e6)))
Javascript:
a=0,b=-1,d=-4,c=1e6;while(c--)a+=(d=-d)/(b+=2)
In javascript. 51 characters. Obviously not going to win but eh. :P
Edit -- updated to be 46 characters now, thanks to Strager. :)
UPDATE (March 30 2010)
A faster (precise only to 5 decimal places) 43 character version by David Murdoch
for(a=0,b=1,d=4,c=~4e5;++c;d=-d)a-=d/(b-=2)
Here's a recursive answer using C#. It will only work using the x64 JIT in Release mode because that's the only JIT that applies tail-call optimisation, and as the series converges so slowly it will result in a StackOverflowException without it.
It would be nice to have the IteratePi function as an anonymous lambda, but as it's self-recursive we'd have to start doing all manner of horrible things with Y-combinators so I've left it as a separate function.
public static double CalculatePi()
{
return IteratePi(0.0, 1.0, true);
}
private static double IteratePi(double result, double denom, bool add)
{
var term = 4.0 / denom;
if (term < 0.00001) return result;
var next = add ? result + term : result - term;
return IteratePi(next, denom + 2.0, !add);
}
Most of the current answers assume that they'll get 5 digits accuracy within some number of iterations and this number is hardcoded into the program. My understanding of the question was that the program itself is supposed to figure out when it's got an answer accurate to 5 digits and stop there. On that assumption here's my C# solution. I haven't bothered to minimise the number of characters since there's no way it can compete with some of the answers already out there, so I thought I'd make it readable instead. :)
private static double GetPi()
{
double acc = 1, sign = -1, lastCheck = 0;
for (double div = 3; ; div += 2, sign *= -1)
{
acc += sign / div;
double currPi = acc * 4;
double currCheck = Math.Round(currPi, 5);
if (currCheck == lastCheck)
return currPi;
lastCheck = currCheck;
}
}
Language: C99 (implicit return 0), Char count: 99 (95 + 4 required spaces)
exit condition depends on current value, not on a fixed count
#include <stdio.h>
float p, s=4, d=1;
int main(void) {
for (; 4/d > 1E-5; d += 2)
p -= (s = -s) / d;
printf("%g\n", p);
}
compacted version
#include<stdio.h>
float
p,s=4,d=1;int
main(void){for(;4/d>1E-5;d+=2)p-=(s=-s)/d;printf("%g\n",p);}
Language: dc, Char count: 35
dc -e '9k0 1[d4r/r2+sar-lad274899>b]dsbxrp'
Ruby:
irb(main):031:0> 4*(1..10000).inject {|s,x| s+(-1)**(x+1)*1.0/(2*x-1)}
=> 3.14149265359003
64 chars in AWK:
~# awk 'BEGIN {p=1;for(i=3;i<10^6;i+=4){p=p-1/i+1/(i+2)}print p*4}'
3.14159
C# cheating - 50 chars:
static single Pi(){
return Math.Round(Math.PI, 5));
}
It only says "taking into account the formula write a function..." it doesn't say reproduce the formula programmatically :) Think outside the box...
C# LINQ - 78 chars:
static double pi = 4 * Enumerable.Range(0, 1000000)
.Sum(n => Math.Pow(-1, n) / (2 * n + 1));
C# Alternate LINQ - 94 chars:
static double pi = return 4 * (from n in Enumerable.Range(0, 1000000)
select Math.Pow(-1, n) / (2 * n + 1)).Sum();
And finally - this takes the previously mentioned algorithm and condenses it mathematically so you don't have to worry about keep changing signs.
C# longhand - 89 chars (not counting unrequired spaces):
static double pi()
{
var t = 0D;
for (int n = 0; n < 1e6; t += Math.Pow(-1, n) / (2 * n + 1), n++) ;
return 4 * t;
}
#!/usr/bin/env python
from math import *
denom = 1.0
imm = 0.0
sgn = 1
it = 0
for i in xrange(0, int(1e6)):
imm += (sgn*1/denom)
denom += 2
sgn *= -1
print str(4*imm)

Resources