Problem 34 - How to approach to the Problem

Back to General discussions forum

Arman Cam     2019-06-15 17:47:35
User avatar

The Problem asks us to find a solution for an equation. And I tried to use sympy solver however its not working. Here is my code

from sympy.solvers import solve
from sympy import Symbol
import sympy

x = sympy.Symbol('x')

A, B, C, D = 0.59912051, 0.64030348, 263.33721367, 387.92069617
equation = solve((A * x) + (B * sympy.sqrt(x**3)) - (C * sympy.exp(-x / 50)) - D).evalf()
print(equation)

I kind of used brute force.

So I did not understand. What kind of an approach should I use ? I read the given text however I feel lost.

Thanks

Rodion (admin)     2019-06-16 04:56:28
User avatar

Arman, hello!

And I tried to use sympy solver however its not working

Not sure what you may mean by "not working", this may work... but...

Using "sympy" for this task is what we call "overengineering" :)

The problem has no trick of any kind, just "implement it". You see it is called "Binary Search" so it is supposed to be solved by binary search.

The problem statement has a link to some explanatory article... You want Math function example part from this article. Hope this helps!

Arman Cam     2019-06-16 07:30:48
User avatar

Thank you Rodion :)

I looked at the binary search and I understand the idea now.

However theres one problem. For instance if the answer for one set of data is

38.8211731863 12.6143430488 61.1255485034 25.9768946287 76.9095343872 12.773444563

I am getting

38.8211731746 12.6143430483 61.1255485427 25.9768946362 76.9095343326 12.5000000000

I have a problem in my last data and this happens all the time, for different sets of data. Any idea why the last element goes like that but others not ?

If you want I can share my code here ? If its not against the rules

Rodion (admin)     2019-06-16 08:39:46
User avatar

Well, it seems you've put a couple of strange things into your algorithm. Speaking strictly it is not the algorithm you want :)

This is confusing for me:

num1, num2 = 0, 100
for i in range(10**4):

we need not that many iterations. moreover it may lead to precision loss (could be seen on some values if reducing amount of iterations).

Now also curious thing:

if abs(func(num1)) > abs(func(num2)):

Why "abs"? and why testing ends? - this definitely is not the correct conditional, though definitely it may work sometimes. :)

Just take func value in the middle between num1 and num2 - your condition should rely only upon this single value.

Arman Cam     2019-06-16 10:11:30
User avatar

For each type of data I should have one larger value then 0 and one less value. However for each case A,B,C,D values are different so just taking 0 and 100 for each case gave me incorrect result I guess.

So I should change the values of num1 and num2 to get achieve a correct algorithm ?

You are right that I put the the num values twice..

I thought that increasing the range increases the accuracy at some level. It actually doesn't after a point so you are right. I ll decreaese the range

I put abs because sometimes func can be return negative values and we are checking the closeness of func(x) to 0. So according to this I thought that If I put

if (func(num1)) > (func(num2)): 

it can take 100 > -50 however actually -50 is closer to zero. I did not understand "why the testing end" part that you asked to me..

I ll re-upload my code again.

Now my code works in every 3 out of 2 cases. I dont understand it... I should use abs otherwise I cannot get correct answer.

Rodion (admin)     2019-06-16 14:50:09
User avatar

I thought that increasing the range increases the accuracy

Well, as this is "binary" search and the range is reduced twice on every step, we get great accuracy just after few dozen steps. However, if you continue, due to finite representation of numbers, num1 becomes equal to num2 and when you sum them and divide by two, it can become slightly reduced for some values...

After 30 iterations we have num2-num1 = 100 / (2^30) i.e. about 1e-7...

Now about algorithm - what you do is more like somewhat broken mix of Newton's algorithm with Binary search :)

See, we know that function is monotonous, so it is:

  • negative at func(num1)
  • positive at func(num2)

Let us use value mid = (num1+num2)/2 - the middle coordinate of the range. Let us check func(mid);

  • if it is greater than zero, then function have crossed zero somewhere in the left half, between num1 and mid. Hence we should reduce range to the left half, i.e. num2 = mid...
  • if on contrary it is less than zero, then function crosses zero somewhere between mid and num2, so we shoul choose other half, i.e. num1 = mid...
Arman Cam     2019-06-16 17:20:31
User avatar

However, if you continue, due to finite representation of numbers, num1 becomes equal to num2 and when you sum them and divide by two, it can become slightly reduced for some values..."

I never noticed that could be the case thanks for your tip

I also understand the algorithm. It's actually very useful... A fun problem to solve.

Thanks for helping me :)

seerozha777     2020-03-19 12:26:18

Hello! I have problem with this task. I think my code (below) is right but my answers is different from yours a little bit. I suppose this is because of some calculation algorithms in my programm and computer and I don't know how to fix it unfortunately.

Could you please check my code? If it's right please help me to pass this problem. Thank you in advance.

import math

filename = 'binary_search.txt'
with open(filename) as f:
    nums = f.readlines()
    for i in range(len(nums)):
        nums[i] = nums[i].rstrip()
        nums[i] = nums[i].split()
    for n in nums:
        for i in range(len(n)):
            n[i] = float(n[i])

for n in nums:
    y = 0
    z = 100
    while True:
        x = (z + y) / 2
        a = n[0] * x + n[1] * math.sqrt(x**3) - n[2] * math.exp(-x/50) - n[3]
        if a < 0:
            y = x
        else:
            z = x
        if len(str(x)) >= 15:
            print(x, end=' ')
            break

my answers = 73.590087890625 41.900634765625 your answers = 73.595368554162 41.899174957955

Rodion (admin)     2020-03-19 12:46:04
User avatar

Hi Friend!

I think your solution is correct but doesn't calculate for enough iterations so the answer is not very precise

if len(str(x)) >= 15:

that is most queer ending condition I ever seen :) Just change it to something more reasonable and most surely you'll get right answers!

Please login and solve 5 problems to be able to post at forum