| Thread overview | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
February 29, 2008 template bug? | ||||
|---|---|---|---|---|
| ||||
In DMD 2.011
import std.stdio;
template factorial(real n)
{
static if (n == 1)
const factorial = 1;
else const factorial = n * factorial!(n - 1);
}
void main()
{
writefln(factorial!(5));
}
produces: -3.10504e+231
when the template is changed to accept an int instead of a real, it produces the right output: 120
What's the cause of this?
Note: in 1.027, the version accepting a real still produces the correct output of 120.
| ||||
February 29, 2008 Re: template bug? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Denton Cockburn | On Fri, 29 Feb 2008 08:35:02 +0300, Denton Cockburn <diboss@hotmail.com> wrote:
> In DMD 2.011
>
> import std.stdio;
>
> template factorial(real n)
> {
> static if (n == 1)
> const factorial = 1;
> else const factorial = n * factorial!(n - 1);
> }
>
> void main()
> {
> writefln(factorial!(5));
> }
>
> produces: -3.10504e+231
>
> when the template is changed to accept an int instead of a real, it
> produces the right output: 120
>
> What's the cause of this?
>
> Note: in 1.027, the version accepting a real still produces the correct
> output of 120.
Seems like a bug to mee, too. This produces incorrect output as well:
template factorial(real n) {
const real factorial = 1;
}
void main() {
writefln(factorial!(5));
}
In C++, one cannot use real as a template parameter. The following code won't compile, although the code looks harmless :)
template<float t> class SomeClass {
static const float someValue = t;
}
void main() {
float value = SomeClass<5.0f>::someValue; // 5.0f expected
}
However this one can easily instanciate as much templates, at it wishes because of rounding error on floating point arithmetics:
template<float t> float factorial() {
if (t == 1) { ///< this condition might never be satisfied
return 1;
} else {
return t*factorial(t-1);
}
}
int main() {
float t1 = factorial<5.0f>();
float t2 = factorial<5.1f>();
}
| |||
February 29, 2008 Re: template bug? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Denton Cockburn | On 29/02/2008, Denton Cockburn <diboss@hotmail.com> wrote:
> template factorial(real n)
Forgive me, but factorial is not defined for real numbers. The domain of factorial is the positive integers only.
Of course, if you want to write a compile-time gamma function! ... :-)
(I know, I know - it's a bug report, not a math lesson. I'll shut up now).
| |||
February 29, 2008 Re: template bug? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Koroskin Denis | On Fri, 29 Feb 2008 12:58:26 +0300, Koroskin Denis wrote: > On Fri, 29 Feb 2008 08:35:02 +0300, Denton Cockburn <diboss@hotmail.com> wrote: > >> In DMD 2.011 >> >> import std.stdio; >> >> template factorial(real n) >> { >> static if (n == 1) >> const factorial = 1; >> else const factorial = n * factorial!(n - 1); >> } >> >> void main() >> { >> writefln(factorial!(5)); >> } >> >> produces: -3.10504e+231 >> >> when the template is changed to accept an int instead of a real, it produces the right output: 120 >> >> What's the cause of this? >> >> Note: in 1.027, the version accepting a real still produces the correct output of 120. > > Seems like a bug to mee, too. This produces incorrect output as well: > > template factorial(real n) { > const real factorial = 1; > } > > void main() { > writefln(factorial!(5)); > } > > In C++, one cannot use real as a template parameter. The following code won't compile, although the code looks harmless :) > > template<float t> class SomeClass { > static const float someValue = t; > } > > void main() { > float value = SomeClass<5.0f>::someValue; // 5.0f expected > } > > However this one can easily instanciate as much templates, at it wishes because of rounding error on floating point arithmetics: > > template<float t> float factorial() { > if (t == 1) { ///< this condition might never be satisfied > return 1; > } else { > return t*factorial(t-1); > } > } > > int main() { > float t1 = factorial<5.0f>(); > float t2 = factorial<5.1f>(); > } D template parameters can be: * types * integral values * floating point values * string literals * templates * or any symbol http://www.digitalmars.com/d/2.0/templates-revisited.html I guess this is a bug. | |||
February 29, 2008 Re: template bug? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Denton Cockburn | On Fri, 29 Feb 2008 18:15:18 +0300, Denton Cockburn <diboss@hotmail.com> wrote:
>> [snip]
>
> D template parameters can be:
>
> * types
> * integral values
> * floating point values
> * string literals
> * templates
> * or any symbol
> http://www.digitalmars.com/d/2.0/templates-revisited.html
>
> I guess this is a bug.
>
I din't say a thing about (in)correctness of this code. In fact, I was talking about C++!
However, you should use this feature with care :)
| |||
February 29, 2008 Re: template bug? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Denton Cockburn | Because of the nature of floating point numbers, you shouldn't use equality(==) to compare floating point numbers.
Instead of n==1 you should write something like abs(n-1)<eps (where eps is a small number)
Denton Cockburn wrote:
> In DMD 2.011
>
> import std.stdio;
>
> template factorial(real n)
> {
> static if (n == 1)
> const factorial = 1;
> else const factorial = n * factorial!(n - 1);
> }
>
> void main()
> {
> writefln(factorial!(5));
> }
>
> produces: -3.10504e+231
>
> when the template is changed to accept an int instead of a real, it
> produces the right output: 120
>
> What's the cause of this?
>
> Note: in 1.027, the version accepting a real still produces the correct
> output of 120.
| |||
February 29, 2008 Re: template bug? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Marius Muja | On Fri, 29 Feb 2008 10:46:23 -0800, Marius Muja wrote:
> Because of the nature of floating point numbers, you shouldn't use equality(==) to compare floating point numbers.
>
> Instead of n==1 you should write something like abs(n-1)<eps (where eps is a small number)
>
That wouldn't explain why it works in 1.027 and not 2.011.
The next thing, it doesn't explain why:
template factorial(real n)
{
static if (n == 1.0L)
const real factorial = 1.0L;
else
const real factorial = 5.0L;
}
void main()
{
writefln(factorial!(5.0L));
}
which is using full real comparisons, and in either case should execute the else even if it doesn't equate, produces an output of -1.49167e-154. 1.027 produces the correct output of 5 again.
P.S. Isn't that how == is defined for floating point numbers already? If not, shouldn't it be that way?
| |||
February 29, 2008 Re: template bug? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Marius Muja | Marius Muja wrote:
> Because of the nature of floating point numbers, you shouldn't use equality(==) to compare floating point numbers.
>
> Instead of n==1 you should write something like abs(n-1)<eps (where eps is a small number)
It's true generally, but integers (up to a point) have an exact representation in floating point. Multiplying exact real integers by exact real integers will yield exact real integers as long as you don't overlflow the mantissa.
-bb
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply