Monte-Carlo method to check triangle inequality This is code for finding if inequality \$abc &gt; 2(\text{area of triangle})\$
 where \$a\$, \$b\$ and \$c\$ are the sides of any triangle.

The below, and repl, code work as intended. However they take a long time. Can the performance be improved without reducing max_tries? 

import random
import math
hn=100000000
num=0
max_tries=10000000
tries = 0
while tries != max_tries:
  a= random.randint(1,hn)
  b= random.randint(1,hn)
  c= random.randint(1,hn)
  if a+b&gt;c and c+b&gt;a and a+c&gt;b :
    s=(a+b+c)/2
    tries= tries +1
    k =math.sqrt(s*(s-a)*(s-b)*(s-c))
    if a*b*c&gt; 2*k:
      num= num+1

print(num/max_tries)
The problem of your code is the way you generate triangles. You just create three independent random numbers. In theory, you could always end up rolling numbers that don't end up in a valid triangle and thus your code would not even terminate. That is, because triangle side lengths are dependent.

To always create a valid triangle, you can instead roll two angles and one side and then use the law of sines to calculate the remaining sides.

The sum of angles in a triangle is 180 degrees (or pi radians). So the first angle alpha is randomly selected between (0, pi), the second angle beta is then between (0, pi-alpha) and the third angle gamma is gained by simple arithmetics: gamma = pi - alpha - beta

Or in code:

alpha = random.uniform(0, math.pi)
beta  = random.uniform(0, math.pi - alpha)
gamma = math.pi - alpha - beta


If we know two sides and the angle in between, we can easily calculate the area. Since your inequality uses twice the area, we can drop the factor of 0.5.

double_area = side_b * side_c * sin_alpha


Some micro-optimisations: math.sin is an expensive function (time-wise), so we save the result in a variable. Same goes for floating point division. Multiplication is faster, so once again, we save the result to use multiplication later on.

Lastly: Since you already know how often you want to execute the loop, you can use a for-loop instead of a while-loop although frankly, I don't know how well this goes in terms of memory consumption.

import math
import random
import time


max_side_length = 100000000
n_max_tries     = 10000000
n_successes     = 0

time_start      = time.time()

for k in range(n_max_tries):
    alpha                   = random.uniform(0, math.pi)
    beta                    = random.uniform(0, math.pi - alpha)
    gamma                   = math.pi - alpha - beta

    side_a                  = random.randint(1, max_side_length)
    sin_alpha               = math.sin(alpha)
    side_a_over_sin_alpha   = side_a / sin_alpha

    side_b                  = side_a_over_sin_alpha * math.sin(beta)
    side_c                  = side_a_over_sin_alpha * math.sin(gamma)

    double_area             = side_b * side_c * sin_alpha

    if side_a * side_b * side_c &gt; double_area:
        n_successes += 1

time_end = time.time()

print("successes: ", n_successes, " / ", n_max_tries, " (", n_successes/n_max_tries, ")")
print("time: ", time_end-time_start)


I didn't do excessive timings because I couldn't be bothered, but this code runs on my machine in about 37.8s, while three runs of your code averaged on 109.8s, resulting in an optimistic speed-up factor of around 3.

Disclaimer: I can somewhat write in python but I'm probably violating this famous pep-8. Yet, I strongly encourage you to give reasonable names to your variables as it makes the code more easy to understand. Not only for others, but also for yourself, when you look at it 2 weeks later.