2

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?

user3427540
  • 1,162
  • 1
  • 14
  • 30

3 Answers3

2

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?

Mark A Kruger
  • 7,183
  • 20
  • 21
  • 1
    Not quite :) If the final value really was `i=4`, then the `if` condition ie `(4*4) > 16` would not equate to true. As [@Sonu](http://stackoverflow.com/a/27042387/104223) pointed out, the behavior is due to [floating point math](http://stackoverflow.com/questions/2002821/why-does-this-subtraction-not-equal-zero). The value of `i` is actually slightly greater than 4 and that is why the `if` condition is executing earlier than he expected. – Leigh Nov 20 '14 at 16:14
  • Got it! I missed that ... read it as "less than". in keeping with the for loop. So yeah, gotta be floating point. – Mark A Kruger Nov 20 '14 at 16:21
  • Darn it. Wish there was not a five minute limit on comment edits! I was trying to add a clarification for the OP to the effect of "Mark already knows this, but based on your code you are probably expecting x instead of y" but got distracted. – Leigh Nov 20 '14 at 17:36
1

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.

sonus21
  • 5,178
  • 2
  • 23
  • 48
1


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.

Tushar Bhaware
  • 2,525
  • 1
  • 16
  • 29
  • Not all CF developers know java. – Dan Bracuk Nov 20 '14 at 16:06
  • @DanBracuk, True. I think if CF developers know a little bit of java then it will help them immensely as CF uses Java under the hood. But that's my opinion. – Tushar Bhaware Nov 20 '14 at 16:11
  • I thought it was a learning exercise :) @Tushar - Java is certainly helpful (when needed). In this case there is already a [CF function](https://wikidocs.adobe.com/wiki/display/coldfusionen/Sqr) for that. – Leigh Nov 20 '14 at 16:25
  • @Leigh, Ouch, totally forgot about that. Thanks for reminding that one. I don't know why i went straight to Java instead of looking in to CF. – Tushar Bhaware Nov 20 '14 at 16:43
  • No worries. There are so many functions now, it is easy to forget a few. Still good to learn about the java options too. Though as I always say "read the java API carefully" ;-) As a strongly typed language, there are some nuances that differ from CF. Things that can bite you if you not aware of them :) – Leigh Nov 20 '14 at 16:53