user3427540
user3427540

Reputation: 1172

strange behavior with Coldfusion loops?

Today I have written small program in ColdFusion to find the square root of a number. I found a strange issue. Not sure am I doing any silly mistake ?

<cfscript>
num = 16;
n = 0.0001;
i = 0;
for (i=0;i<num;i=i+n)
{
    if((i*i)>num){
        i = i - n;
        break;
    }
}
writedump(i);
</cfscript>

The output is 3.999 instead of 4 when num = 16. Where as when I set it to 36 its output is 6. Not sure why I am getting 3.999 where as it should be 4.Any suggestion?

Upvotes: 2

Views: 95

Answers (3)

sonus21
sonus21

Reputation: 5388

There is a problem in the if condition. When you use num=36 in that case at 6.001 the if condition gets evaluated and you get 6. But in the case of num=16 the if condition gets evaluated at 4.00 and you get 3.999. But you may ask why at 4.00 it gets evaluated due to floating point numbers and floating point arithmetic.
Edit:
You can use Newton method to find square root of any +ve number.By this method you can achieve better performance over for loop that you had used.

Upvotes: 1

Tushar Bhaware
Tushar Bhaware

Reputation: 2525


Why do you want to do all the heavy lifting when we can use power of java as below:

<cfset testNumber = 20.50 />
<cfset mathObj = createObject( "java", "java.lang.Math" ) />
<cfset sqrtNumber = mathObj.sqrt(testNumber) />
<cfdump var="#sqrtNumber#"><cfabort>

Output:

4 -> 2
6 -> 2.44948974278
36- > 6
20.50 - > 4.52769256907

As you can see it works on all values including decimals. I hope this helps.
Note: Before passing values to the mathObj.sqrt, you should first check for negative values. You can not have sqrt of negative numbers.
Edit:
As Leigh pointed out there is already a function in CF, you can use that as follows:

<cfset testNumber = 36 />
<cfset sqrtNumber = sqr(testNumber) />

You will get output same as Java version code, only difference is that when you pass negative value in java code, you will get a gibberish value. With CF, you will get an error like this The 1 parameter of the Sqr function, which is now -122.0, must be a non-negative real number.

Upvotes: 1

Mark A Kruger
Mark A Kruger

Reputation: 7193

I altered your code to output the conditions you are seeing like so:

<cfscript>
num = 16.00;
n = 0.0001;
i = 0;
for (i=0;i<num;i=i+n)
{
     writeoutput(i & " i * i = " & (i*i));
     writeoutput('<br>');
    if((i*i)>num){
        i = i - n;
        break;
    }
}
writedump(i);
 writeoutput('<br>');
</cfscript>

This outputs all the numbers and the multiples - a long list. The last 3 lines look like this:

3.9999 i * i = 15.99920001
4 i * i = 16
3.9999 

That seems like expected behavior to me. Inside your break code you are reducing the value of i with this line:

i = i - n;

Is that not what you want?

Upvotes: 2

Related Questions