Counting the number of decimal places in pascal

Tag: pascal , decimal , real Author: xiaobenmao2009 Date: 2013-04-28

I just started studying pascal and I have to do a pascal program as homework. I made it but i don't know how to count the number of decimal places in a real number (the number of digit after the "."). I need it just to format well a real number (like write(real:0:dec) where dec is the number of decimal digit i don't know how to know). I'd like to do that because i don't want it in scientific notation or with many unnecessary zeros.

For example if a real number is 1.51 (x) and I write writeln(x:0:4); or WriteLn(Format('%*.*f', [0, 4, x])); it will show 1.5100 but I want it to be just 1.51; and if the number is like 1.513436, it will show only 1.5134 . So I would make it like writeln(x:0:dec); with something that makes dec the number of decimal digits of x.

Sorry for my English but i'm Italian.

You added the general "Pascal" tag. Please mention compiler/dialect of Pascal.

Best Answer

The Format() function is normally used in situations like this.

WriteLn(Format('%*.*f', [0, dec, your_real_number]));

*.* is interpreted as total_characters.decimal_digits. Passing zero for the first means that width is adjusted according to how large your real is. The number of decimals can be a variable (dec), which you can adjust to your specification.


Update:

You mention that you want an exact representation of a float with respect to the number of decimals.

As mentioned in my comment, most floating point values does not have a finite number of decimals. And most decimal fractions cannot be represented by a binary type.

There are some libraries that can handle floating point values of arbitrary size. See TBigFloat for example. There is a formatting routine that can strip redundant zeroes from a decimal float.


Still, there is a possibility to remove trailing zeroes by using the general format specifier:

WriteLn(Format('%g',[your_real_number]));

You can specify the width and the number of significant digits as well.

comments:

Thanks, but i still don't understand how can I format a number showing just the needed digit. For example if a real number is 1.51 (x) and I write writeln(x:0:4); or WriteLn(Format('%*.*f', [0, 4, x])); it will show 1.5100 but I want it to be just 1.51; and if the number is like 1.513436, it will show only 1.5134 . So I would make it like writeln(x:0:dec); with something that makes dec the number of decimal digits of x.
Floating point values often does not have a finite number of decimals. Also the binary representation of a float often cannot hold more than a few decimals to a exact value. A single type cannot represent 0.1 exactly as an example. See this blog, Floating point numbers for a good pascal summary of floating point values. Here is one more link, How deal with the fact that most decimal fractions cannot be accurately represented in binary?.
Format() is not pascal, but specific for Delphi and compatibles.
@MarcovandeVoort, ok. I assumed it was Free Pascal, perhaps it was wrong.
Delphi and FPC together is the bulk of Pascal nowadays. But they have their own (set of) tags. Please help keep [pascal] a bit pure.

Other Answer1

if you're actually doing a writeln() output, surely just writeln(x); would accomplish what you're after? If you actually want to count the number of decimals, you'd probably have to convert to a string, remove any trailing zeroes, and see where the decimal point landed.

Other Answer2

For example, if you have input x=1.51 in real variable type, then you write only writeln(x), the output will be 1.5100000000. If you write writeln(x:0:3), the output will be 1.510 (3 digits after ".") ...

var x: real;
Begin
x:=1.51;
writeln(x); //output 1.5100000000
writeln(x:0:4); //output 1.5100 (4 digits after ".")
writeln(x:0:2); //output 1.51 (2 digits after ".")
readln;
End.

From your other example, if your input is 1.512426, with writeln(x:0:5) it will only show 5 digits after "." and the output will be 1.51242

var x: real;
Begin
x:=1.512426;
writeln(x); //output 1.5124260000
writeln(x:0:4); //output 1.5124 (4 digits after ".")
writeln(x:0:2); //output 1.51 (2 digits after ".")
readln;
End. 

So, if you write writeln(x:0:dec) the output will be "dec" digits after "."

Hope this helps, I'm just trying to answer from a different perspective.