Optimizing Electric Potential Calculation for a Charged Particle in 1-Dim

  • Thread starter Thread starter Saladsamurai
  • Start date Start date
  • Tags Tags
    Operator
Click For Summary

Discussion Overview

The discussion revolves around optimizing the calculation of electric potential for a charged particle in one dimension, specifically addressing issues related to evaluating the function at a point where it is undefined (f(0)). Participants explore programming logic and floating-point precision in a coding context.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • One participant describes a program that uses a user-defined function for electric potential, noting the need to avoid evaluating the function at zero due to its undefined nature.
  • Another participant questions how the compiler interprets the conditional statements and suggests that the logic may not be functioning as intended.
  • Some participants point out the challenges of comparing floating-point numbers to zero, suggesting that due to precision issues, dist may not equal exactly zero during the loop.
  • A suggestion is made to convert the floating-point number to an integer or to check if it falls within a small range around zero to avoid the undefined evaluation.
  • Participants discuss the implications of using brackets in conditional statements and how it affects the scope of variables like V.
  • One participant expresses confusion about how to implement the suggested checks and continues to seek clarification on the logic required to skip the evaluation at zero.
  • A later reply provides a working solution using a conditional statement that checks if dist is within a small range around zero, allowing the loop to continue without evaluating the function at that point.
  • There is also a mention of the possibility of using integer conversion to avoid the issue, though some participants express uncertainty about its effectiveness.

Areas of Agreement / Disagreement

Participants generally agree on the issue of floating-point precision affecting the evaluation of the function at zero, but there is no consensus on the best method to handle this in the code. Multiple approaches are proposed, and the discussion remains unresolved regarding the optimal solution.

Contextual Notes

Participants note limitations related to floating-point arithmetic and the potential for unexpected behavior when comparing such values to zero. The discussion highlights the need for careful handling of conditions in programming to avoid undefined evaluations.

Saladsamurai
Messages
3,009
Reaction score
7
so the following program uses a user defined function called epotential which is basically a function of the form f(x)=c/x where c is a constant.

I am using a for loop to evaluate the function from -0.5 to +0.5 and incrementing by 0.1

The problem is that I do not want it to evalute f(0) since it is undefined.

I thought that I could simply put "if (x!=0)...evaluate the function"

but this is not working and I do not see what is wrong with that logic.

Can someone help me out here?

Code:
#include <iostream>
#include <fstream>         // needed for outfile
using namespace std;


double epotential (double charge, double dist);     // function prototype

int main ()

{
    ofstream outfile;             
    outfile.open ("ePotential.txt");           // opens textfile
    
    //declare and initialize objects
    
    double charge=8.0*0.000000001;
    double dist;
    double V;
    
    
    outfile <<"x= " << '\t' << "V= " <<endl << endl;         //cout to textfile
    cout << "x= " << '\t' << "V= " <<endl << endl;           //cout to screen
    
    double inc = 0.1;            // increment in for loop
    double left_bound = -0.5;    // left bound of domain of x
    double right_bound = 0.5;    // right bound of domain of x
    

    for (dist= left_bound; dist <= right_bound; dist+=inc)
    
    {
           if (dist != 0)  // I do not want it to output V if dist = 0
                           // why does this not work?!
                           
           V=epotential(charge, dist);               // loops over domain of x
           outfile << dist << '\t' << V << endl;     // sends output to textfile   
           cout << dist << '\t' << V << endl;        // sends output to screen
        
    }
    
    system ("PAUSE");                    // for Dev C++ compiler
    return 0;
}
        
        


        
    
    
//function that calculates the electric potential of a charged particle in 1-dim
/*---------------------------------------------------------------------*/
/*---------------------------------------------------------------------*/

double epotential (double q, double r)  
{
       double V;
       double k=9.0*1000000000;
       
       V=k*(q/r);
       
       return (V);
}

Here is the output

x= V=

-0.5 -144
-0.4 -180
-0.3 -240
-0.2 -360
-0.1 -720
-2.77556e-017 -2.59407e+018
0.1 720
0.2 360
0.3 240
0.4 180
0.5 144
 
Technology news on Phys.org
if (dist != 0) // I do not want it to output V if dist = 0
// why does this not work?!

V=epotential(charge, dist); // loops over domain of x
outfile << dist << '\t' << V << endl; // sends output to textfile
count << dist << '\t' << V << endl; // sends output to screen

How the compiler knows when to stop if?

Or, how would you write the following code?

int main ()
{
if condition met:
do something

do something all times
}
 
You can't compare the rest of a floating point calculation to 0
As dist is incremented it might equal 0.00000000000001 an so the test fails
You need to convert to an int or check for a range.
 
rootX said:
How the compiler knows when to stop if?

Or, how would you write the following code?

int main ()
{
if condition met:
do something

do something all times
}

I am sorry I don't follow. I more or less have the following:

for x=-0.5 to 0.5 (increment by 0.1)

if x not equal to 0
evaluate V(x)


mgb_phys said:
You can't compare the rest of a floating point calculation to 0
As dist is incremented it might equal 0.00000000000001 an so the test fails
You need to convert to an int or check for a range.

Sorry don't follow this either? I am an amateur, so bare with me. I am looping through the domain -0.5 to 0.5 and incrementing by 0.1 ... so at one point dist = 0 .

So what is the problem here?
 
Saladsamurai said:
I am sorry I don't follow. I more or less have the following:

for x=-0.5 to 0.5 (increment by 0.1)

if x not equal to 0
evaluate V(x)

Forgetting the brackets.

V=epotential(charge, dist); // loops over domain of
outfile << dist << '\t' << V << endl; // sends output to
count << dist << '\t' << V << endl; // sen

In my VS, if I don't include brackets, only first line below the if is considered a part of it. You have three lines and you define V to be under if, but then accessing V outside the scope of if condition. I only read that part of the code but wonder if this would create any problems
Sorry don't follow this either? I am an amateur, so bare with me. I am looping through the domain -0.5 to 0.5 and incrementing by 0.1 ... so at one point dist = 0

There's nothing like exact 0 , 0.5, or 0.1.
 
rootX said:
Forgetting the brackets.

V=epotential(charge, dist); // loops over domain of
outfile << dist << '\t' << V << endl; // sends output to
count << dist << '\t' << V << endl; // sen

In my VS, if I don't include brackets, only first line below the if is considered a part of it. You have three lines and you define V to be under if, but then accessing V outside the scope of if condition. I only read that part of the code but wonder if this would create any problems

Okay, I think that I tried that. I understand now.
There's nothing like exact 0 , 0.5, or 0.1.

Do you mean when it adds 0.1 + -0.1 it does not equal EXACTLY zero ?

Is that what you are saying?
 
Saladsamurai said:
Do you mean when it adds 0.1 + -0.1 it does not equal EXACTLY zero ?

Is that what you are saying?

Yes. See ~third post:
As dist is incremented it might equal 0.00000000000001 an so the test fails

http://idlastro.gsfc.nasa.gov/idl_html_help/Accuracy_and_Floating_Point_Operations.html
 
Last edited by a moderator:
rootX said:
Yes. See ~third post:


http://idlastro.gsfc.nasa.gov/idl_html_help/Accuracy_and_Floating_Point_Operations.html

Gotcha. Thanks!

I am not sure, though, how I can convert this to int ...?
 
Last edited by a moderator:
Either do
if ((int)dist == 0 ) or
if ( (dist > -0.00001) && (dist < 0.00001) )
 
  • #10
mgb_phys said:
Either do
if ((int)dist == 0 ) or
if ( (dist > -0.00001) && (dist < 0.00001) )

You mean if((int)dist != 0) right?

Since I do not want f(0)
 
  • #11
This is getting silly.

If I replace if (dist != 0)with if ((int)dist != 0) nothing from the loop gets outputted
if I replace it with

if ((int)dist == 0) i get the same output as before

mgb_phys said:
Either do
if ((int)dist == 0 ) or
if ( (dist > -0.00001) && (dist < 0.00001) )

if I want to use either of these, I have to tell the compiler that if (int)dist == 0

then DONT evaluate f(dist)

and I cannot figure out how to do that. Any ideas?
 
Last edited:
  • #12
Ha ha! Gotcha!

Code:
 for (dist= left_bound; dist <= right_bound; dist+=inc)
    
    {
           if ((dist > -0.00001) && (dist < 0.00001))
           {continue;}
                           
           else                
            {
            V=epotential(charge, dist);               // loops over domain of x
            outfile << dist << '\t' << V << endl;     // sends output to textfile   
            cout << dist << '\t' << V << endl;        // sends output to screen
           }      
    }


There has to be a way using int though...
 
  • #13
Saladsamurai said:
Ha ha! Gotcha!

Code:
 for (dist= left_bound; dist <= right_bound; dist+=inc)
    
    {
           if ((dist > -0.00001) && (dist < 0.00001))
           {continue;}
                           
           else                
            {
            V=epotential(charge, dist);               // loops over domain of x
            outfile << dist << '\t' << V << endl;     // sends output to textfile   
            cout << dist << '\t' << V << endl;        // sends output to screen
           }      
    }
There has to be a way using int though...

Well, int converts float to an integer: -1,0,1
so int (0.5) would obviously round down to 0 not 1.
I think one of the way to use int would be multiply by like 1000 before converting to int.
 
  • #14
You don't need to use integers.

As you saw, two numbers that are the same on paper can be different on a computer. It is usually not a good idea to compare two doubles for equality. It is much safer to test for "reasonably close to the same", where "reasonably close" application specific. Here you are incrementing by 0.1 (more on this below) from -0.5, so the fifth increment should put you somewhere close to zero. So test for that -- zero plus or minus some small epsilon.

The problem here is that 0.1 (decimal) in binary is 0.000110001100011... It's binary representation is non-terminating, just as 1/3 has a non-terminating decimal expansion. A rational number with a non-terminating binary expansion cannot be represented exactly using the standard computer representation for doubles. By comparing with ==, you are acting as if the computation is exact. It isn't.
 
  • #15
rootX said:
Well, int converts float to an integer: -1,0,1
so int (0.5) would obviously round down to 0 not 1.
I think one of the way to use int would be multiply by like 1000 before converting to int.

This would also be a good time to pull out the floor(), ceiling() and round() functions from math.h.

(Although come to think of it is it guaranteed that round( n ) == 0 where -0.5 < n < 0.5 ?)
 
  • #16
You could always try a trick like this:


Code:
for(int i = 0; i < 11; i++)
{
   if(i != 0)
   {
      double dist = (i - 5) * 0.1;
      // code...
   }
}


Essentially, since you will be using a finite discrete number of values for dist, there exists a mapping from integers to reals. And since integers are computed exactly (in the ranges, anyway) this will work *every* time. You could even generalize the code to work with arbitrary bounds. For instance...

Code:
double proportionalMapping(double min, double max, int sampleSize, int i)
{
   return min + (max - min) * i / (sampleSize-1);
}

Then your original code could look like

Code:
const int sampleSize = 11;
const double min = -0.5, max = 0.5;

for(int i = 0; i < sampleSize; i++)
{
   if(i != 0)
   {
      double dist = proportionalMapping(min, max, sampleSize, i);
   }
}
 

Similar threads

  • · Replies 23 ·
Replies
23
Views
3K
  • · Replies 10 ·
Replies
10
Views
13K
  • · Replies 7 ·
Replies
7
Views
10K
  • · Replies 2 ·
Replies
2
Views
17K
Replies
20
Views
2K
  • · Replies 14 ·
Replies
14
Views
3K
Replies
5
Views
2K
  • · Replies 3 ·
Replies
3
Views
3K
Replies
4
Views
10K
  • · Replies 1 ·
Replies
1
Views
2K