I figured modern compilers are usually smarter than the programmer writing them. So, in all likelihood, it’s better to write clear and concise code and let the compiler sort out the optimization. But, in the interest of science, the compiled bytecode is different (for now). Although the JIT’er is free to do it’s own optimizations.
Typically I’d prefer code in Cone_A because it’s more easily debugged and easier to understand that it’s been coded correctly.
public class Cone_A
{
public double Radius { get; set; }
public double Height { get; set; }
public double ComputeVolume()
{
double result = Math.PI * Math.Pow(Radius, 3) * Height;
result /= 3.0;
return result;
}
}
public class Cone_B
{
public double Radius { get; set; }
public double Height { get; set; }
public double ComputeVolume()
{
return ( Math.PI * Math.Pow( Radius, 3) * Height) / (3.0);
}
}
The result, Cone_B::ComputeVolume() is much smaller in release mode. Execution time wasn’t tested.
I apologise for the long post, but it’s the only way to shut people up.
//In .net, DEBUG version of code. Cone_A::ComputeVolume
.method public hidebysig instance float64
ComputeVolume() cil managed
{
// Code size 57 (0x39)
.maxstack 3
.locals init ([0] float64 result,
[1] float64 CS$1$0000)
IL_0000: nop
IL_0001: ldc.r8 3.1415926535897931
IL_000a: ldarg.0
IL_000b: call instance float64 Inlining.Cone_A::get_Radius()
IL_0010: ldc.r8 3.
IL_0019: call float64 [mscorlib]System.Math::Pow(float64,
float64)
IL_001e: mul
IL_001f: ldarg.0
IL_0020: call instance float64 Inlining.Cone_A::get_Height()
IL_0025: mul
IL_0026: stloc.0
IL_0027: ldloc.0
IL_0028: ldc.r8 3.
IL_0031: div
IL_0032: stloc.0
IL_0033: ldloc.0
IL_0034: stloc.1
IL_0035: br.s IL_0037
IL_0037: ldloc.1
IL_0038: ret
} // end of method Cone_A::ComputeVolume
//DEBUG Cone_B::ComputeVolume
.method public hidebysig instance float64
ComputeVolume() cil managed
{
// Code size 53 (0x35)
.maxstack 3
.locals init ([0] float64 CS$1$0000)
IL_0000: nop
IL_0001: ldc.r8 3.1415926535897931
IL_000a: ldarg.0
IL_000b: call instance float64 Inlining.Cone_B::get_Radius()
IL_0010: ldc.r8 3.
IL_0019: call float64 [mscorlib]System.Math::Pow(float64,
float64)
IL_001e: mul
IL_001f: ldarg.0
IL_0020: call instance float64 Inlining.Cone_B::get_Height()
IL_0025: mul
IL_0026: ldc.r8 3.
IL_002f: div
IL_0030: stloc.0
IL_0031: br.s IL_0033
IL_0033: ldloc.0
IL_0034: ret
} // end of method Cone_B::ComputeVolume
// And again, in RELEASE mode. Cone_A::ComputeVolume
.method public hidebysig instance float64
ComputeVolume() cil managed
{
// Code size 52 (0x34)
.maxstack 3
.locals init ([0] float64 result)
IL_0000: ldc.r8 3.1415926535897931
IL_0009: ldarg.0
IL_000a: call instance float64 Inlining.Cone_A::get_Radius()
IL_000f: ldc.r8 3.
IL_0018: call float64 [mscorlib]System.Math::Pow(float64,
float64)
IL_001d: mul
IL_001e: ldarg.0
IL_001f: call instance float64 Inlining.Cone_A::get_Height()
IL_0024: mul
IL_0025: stloc.0
IL_0026: ldloc.0
IL_0027: ldc.r8 3.
IL_0030: div
IL_0031: stloc.0
IL_0032: ldloc.0
IL_0033: ret
} // end of method Cone_A::ComputeVolume
// RELEASE Cone_B::ComputeVolume
.method public hidebysig instance float64
ComputeVolume() cil managed
{
// Code size 48 (0x30)
.maxstack 8
IL_0000: ldc.r8 3.1415926535897931
IL_0009: ldarg.0
IL_000a: call instance float64 Inlining.Cone_B::get_Radius()
IL_000f: ldc.r8 3.
IL_0018: call float64 [mscorlib]System.Math::Pow(float64,
float64)
IL_001d: mul
IL_001e: ldarg.0
IL_001f: call instance float64 Inlining.Cone_B::get_Height()
IL_0024: mul
IL_0025: ldc.r8 3.
IL_002e: div
IL_002f: ret
} // end of method Cone_B::ComputeVolume