Thank you Winni for the answer, but no "version" of rounding will do the job. The 8th number has to go to the 3rd level as all numbers up to 15. The 16th number up to the 31. goes to level 4. This could (and should) be calculated by the trunc-function (trunc(log2(number)) respectively). My question is, why it doesn't. Is this a bug in FPC?
I use always an interger based log function for this sort of thing:Untested, but something like that should do the job.
function ilog2(value: integer): Integer; begin Result := 0; While value shr Result > 0 do Inc(result); end;
Ok, so why aint any one using them ?
May I ask you what "dedicated function" means. As I understand from your answer it must be some "better version" of calculating log2 in a unique way for each number. Am I wright? Why isn't this implemented in 64bit?
May I ask you what "dedicated function" means. As I understand from your answer it must be some "better version" of calculating log2 in a unique way for each number. Am I wright? Why isn't this implemented in 64bit?
No, there is not, because Double which is the highest available floating point type available on Win64 as well as any non-x86 system simply cannot represent 3 exactly (as well as many other values). So no matter what you do, Trunc of that will simply return 2 (in case its Double representation is less than 3) and that is correct.
recently I discovered that Lazarus/FreePascal calculatesas 2.
Trunc(Log2(8))
May I ask you what "dedicated function" means. As I understand from your answer it must be some "better version" of calculating log2 in a unique way for each number. Am I wright? Why isn't this implemented in 64bit?
No, there is not, because Double which is the highest available floating point type available on Win64 as well as any non-x86 system simply cannot represent 3 exactly (as well as many other values). So no matter what you do, Trunc of that will simply return 2 (in case its Double representation is less than 3) and that is correct.
I beg to differ here. The value 3 can be represented exact as a finite binary floating point value (in fp32 single, fp64 double or fp80 extended). What can not be represented exact as a finite binary floating point value is e.g. 0.1 (aka one tenth).
I've looked at the problem again and what might work is to tweak the 1/ln(2) constant that is used inside log2 for each of the supported maximum floating point type. E.g. the current one is 1.4426950408889634079 which is correct for Extended, but for Double the value t1.4426950408889635 results in more correct values (at least they're overestimating instead of underestimating). Similar for Single and probably also for log10.
in the binary system. But why is the calculation in question different in Win32 and Win64?
I understand, that - in general - decimal numbers can not be represented exactly in the binary system. But why is the calculation in question different in Win32 and Win64?
Is it so, that for some numbers the calculation gives the expected result and for others not - dependent from the conversation from binary to decimal? If this is the case then for some numbers the outcome of trunc(log2(number)) might be as expected in Win32 - for others in Win64.
I've looked at the problem again and what might work is to tweak the 1/ln(2) constant that is used inside log2 for each of the supported maximum floating point type. E.g. the current one is 1.4426950408889634079 which is correct for Extended, but for Double the value t1.4426950408889635 results in more correct values (at least they're overestimating instead of underestimating). Similar for Single and probably also for log10.
I suspected that much, when I saw the code excerpt provided by Bart. Is it possible to define floats in hex format (within the scope of system libraries at least)? This could eliminate rounding errors introduced by StrToFloat conversions. Because in theory the specific constant here would need to have decimal representations of 24, 54 or 65 decimal digits - and depending on the lib for conversion to float these may get rounded different.