function TruncWithInt(const X: Double): Double;
begin
Result := Int(X * 100) / 100;
end;
function TruncWithTrunc(const X: Double): Double;
begin
Result := Trunc(X * 100) / 100;
end;
function TruncWithStr(const X: Double): Double;
var
S: string;
P: integer;
begin
S := FloatToStr(X);
P := Pos(DecimalSeparator, S);
if P > 0 then
S := Copy(S, 1, P-1) + DecimalSeparator + Copy(S, P+1, 2);
Result := StrToFloat(S);
end;
In agreement with thousands of tests that I did, TruncWithStr just works as
expected. But TruncWithStr is also the slowest.
Which alternative does work like TruncWithStr, but what is fast?
Daniel
Can you tell us what rounding you would like to see?
There are many kinds, such as
floor, ceil, bankers, trunc, etc. and
the type that you see with round(x*100)/100).
Example:
1.45678 ===>>> 1.45
1.55555 ===>>> 1.55
2.55555 ===>>> 2.55
2.45678 ===>>> 2.45
John Herbster <jo...@petronworld.com> escreveu nas notícias de
mensagem:3b2a2e06$1_2@dnews...
Daniel,
That sounds very close to what trunc(x*100)/100 would do. But if
you are working with floating binary point numbers (FBPN) (i.e.
double, single, extended), then you have to program with some fudge
factors. This is because when you store a number like 1.13 into a
FBPN variable like a double, you don't store exactly 1.13. Instead
it is stored as +1.12999 99999 99999 89341 85896 35984 97211 93313
59863 28125. So if you ran 1.13 through your trunc method it would
truncate toward zero and you would get something very close to 1.12,
which is not what you want.
--
Regards, John H
(Support the Movement to Include Fixed and
Floating Decimal Fraction Numbers in Delphi)
> (Support the Movement to Include Fixed and
> Floating Decimal Fraction Numbers in Delphi)
No!
-- Barry
John Herbster <jo...@petronworld.com> escreveu nas notícias de
mensagem:3b2a328a$1_2@dnews...
Daniel, If you mean "at wits end", then why don't you try something
like the following? Regards, JohnH
function MyRound(x: extended): extended;
const Fudge = 0.0001;
begin
If x >=0
then result := trunc(x*100+Fudge)/100
else result := trunc(x*100-Fudge)/100;
end;
PS: Don't get upset with Barry. He's really pretty smart most of
the time!
> I am without exit. Currency just supports 4 digits after the point. It
> doesn't solve all the cases. Double causes problems of roundings!!!
Currency is the most accurate for supporting 2 digits of accuracy
(yes, I know it provides 4 digits but this is *in order to* provide 2
digits of accuracy).
Double is based on binary representation of floating point values. You
want to truncate a *decimal* value. There isn't a one for one
correspondence between decimal values and binary values.
For this reason, if you need more accuracy that Currency, and you need
decimal accuracy, you need to work with some other representation -
like BCD or scaled integers.
-- Barry
--
One must sometimes choose between expressiveness, safety, and
performance. But a scarcity of one isn't always excused by an
abundance of another. - Thant Tessman
Team JEDI: http://www.delphi-jedi.org
NNQ - Quoting Style in Newsgroup Postings
http://web.infoave.net/~dcalhoun/nnq/nquote.html
Barry Kelly <dyn...@eircom.net> escreveu nas notícias de
mensagem:qbkkitobnpge0foce...@4ax.com...
Yes!
(Why not? Given that Delphi does supports such weird entities as
Boolean and String).
Manuel Algora
m...@encomix.es
Daniel, D5 includes a type named "TBCD" but no routines that I can
find for working with it. So I put +TBCD +Delphi +arithmetic into
http://www.google.com and found the following leads. Regards, JohnH
http://www.turbopower.com/products/SysTools/bcd/
Describes TruboPower's type TBCD which may or may not be the same as
Delphi's TBCD.
http://home.kimo.com.tw/bruce0211/Kylix/15652/chapter02.html
By Charlie Calvert, describing the Kylix (and maybe D6) Advanced
Features of the Object Pascal Syntax which includes a mention of new
routines for handling the TBcd type.
This function fails.
MyRound(0.559999) = 0.56
Manuel Algora <m...@encomix.es> escreveu nas notícias de
mensagem:ttukitc1id9ceu1tl...@4ax.com...
How much precision do you need? You can always change the Fudge
constant (e.g., Fudge = 0.0000001).
Daniel, As Eric, pointed out, you can change the fudge factor to
suit your application. But, if you make it too small, then you will
have a problem like:
var s1,s2: single;
begin
s1 := 0.13;
s2 := MyRound(s1);
ShowMessage(FormatFloat('#0.00',s2));
end;
showing "0.12". The exact values will be
s1 = +0.12999 99952 31628 41796 875
s2 = +0.11999 99973 17790 98510 74218 75
As you can see, there are problems with mixing floating binary point
numbers and decimal fractions.
Regards, JohnH
BUT!
There is a floating point decimal problem in the processor on all Intel and
clone systems. Certain numbers CANNOT be represented exactly, so you enter
4.03, and the computer thinks it's 4.029999999999999999.
Sometimes the best solution if you need 2 place accuracy is to store values as
"cents" in INTEGER vars, and only convert them to display or store them in
databases.
Daniel / Tecnobyte wrote:
--
Bryan Valencia
Software Development Engineer
> There is a floating point decimal problem in the processor on all Intel
and
> clone systems. Certain numbers CANNOT be represented exactly, so you
enter
The problem is not with the Intel or any other CPU. Its not a "problem" but
a characteristic/limitation of the storage format. All CPU/FPU have the same
behavior with "floating point" formats.
Bruce Roberts wrote:
--
> Sorry, but BCD math units (like the one in my old Atari 800) never had this
> problem.
They are still fixed precision.
Also, BCD aren't floating-point; they can't deal efficiently with very
large / very small numbers.
-- Barry
--
If you're not part of the solution, you're part of the precipitate.
I'm sure they didn't. Just as BCD on Intel and other CPU don't have this
problem. But BCD is not a "floating point" format.
> There is a floating point decimal problem in the processor on all Intel and
> clone systems.
No, this is not correct. ALL floating point processors will have errors. Here is
why.
It is not possible to exactly represent many decimal fractions in a binary float
field. For example, 0.1 cannot be represented exactly in a 32 bit float with a 23
bit mantissa. It is not the number of decimal digits, but rather whether the
number can be represented in terms of 1 / (2^n) where n is the bit position in the
mantissa. For example
bit 1 - 1 / (2^1) = 0.5
bit 2 - 1 / (2^2) = 0.25
bit 3 - 1 / (2^3) = 0.125
bit 4 - 1 / (2^4) = 0.0625
and so on until you get to
bit 23 - 1 / (2^23) = 0.00000011920928955078125
No matter how you combine the bits you cannot get to 0.1, although you can get
close.
Currency information must be stored as integer values with implied decimal
places. Unfortuntely, although Delphi offers a currency type with 4 implied
decimal places, the field definitions for currency are of type float, and the
error will crop up. You might save the currency fields as strings to avoid this
problem.
The other problem with reals in a computer is that they are not continuous but are
only a subset of all possible reals. For Intel type CPU’s the real formats are as
follows:
Type Min to Max Value Mantissa Exponent
Single 1.5 x 10-45 .. 3.4 x 10 38 7-8 4
Double 5.0 x 10-324 .. 1.7 x 10 308 15-16 8
Extended 3.4 x 10-4932 .. 1.1 x 10 4932 19-20 10
(Source – Delphi V5 doc files)
Because of the limited number of digits in the mantissa, there are only a finite
set of real numbers that can be represented. To simplify for an example: suppose
that we have a mantissa of 1 place and an exponent of 1 place. Then, 1 E 0 is 1,
2 E 0 is 2, and so on... note that you cannot represent 2.1 with a limited
mantissa. Similarly, 1 E 1 is 10, 2 E 1 is 20, and so on, so you can't even
represent 11, 12, 13, and so on. 1 E 2 is 100, 2 E 2 is 200, so you have a gap of
100 real numbers in between each representable number... you cannot represent 150
with this limited example data type. This problem is partially alleviated by using
double, 64 bit reals which have many bits in the mantissa, but as the exponent
becomes very large... or very small, you get large gaps in the number system...
maintaining numerical accuracy is a big problem in areas such as the computation
of orbits and space craft trajectories.
Please show me the decimal value your old Atari used for the square root of
2?
You don't even need an irrational number. 1/3 would do it. Also, I am
certain that it would be possible to work out a simple number that a
bicimal system can represent precisely that a decimal system can't. Just as
1/3 in base three would be 0.1 while it is a recurring decimal, I am sure
there would be equivalent examples for bicimal.
--
John Carlyle-Clarke, Software Engineer
Blakell Europlacer, Blandford
"Many have tried to formulate rules for software development. We are
guided by the ways in which they fail to work."
(S. O'Hara-Smith, a.f.c)
BCD implementations *can be* floating point.
So I guess the phrase "deal with" can cut both ways.
John Herbster wrote:
--