8

I have started using maxima just a few weeks ago (actually I have just used it a few times) with the wxMaxima interface for OS X.

I have tried to find a solution for this around the web, but maybe because I am blind or maybe because I do not have much experience in searching in the official documentation of maxima, I have not find a concrete solution yet.

How do I approximate a number to a n number of decimal places? For example, if I use float(22/7), it gives me this huge number 3.142857142857143, but I just want for example to approximate it to the 3rd decimal place 3.143.

nbro
  • 15,395
  • 32
  • 113
  • 196

5 Answers5

8

fpprec controls the actual number of significant digits in a Maxima bigfloat. That applies only to bigfloats and not to ordinary (fixed precision, IEEE 754) floats.

See also fpprintprec which controls how many digits are printed, which applies to bigfloats and to ordinary floats alike. So another solution for you is:

(%i1) fpprintprec : 4 $
(%i2) float (22/7);
(%o2)                                3.143
Robert Dodier
  • 16,905
  • 2
  • 31
  • 48
  • Well, it does not only controls how many digits are printed, but you can also approximate a variable. `fpprintprec : 4, x:float(%pi);`. `x` will then contain `3.145`. Am I right? – nbro Mar 30 '15 at 00:33
  • @Rinzler No, `fpprintprec` doesn't have any effect on the value of a variable (neither float nor bigfloat). When you assign `float(%pi)` to `x`, it is the same value no matter what `fpprintprec` is. Try changing `fpprintprec` and output `x` again. You will see different numbers of digits. – Robert Dodier Mar 30 '15 at 16:32
  • Is there a way to change the variable? I would need for example to compare some results (which I need to approximate to 3 decimal digits) of a function to the approximate value of the number of euler `2.718`, instead of comparing to the number given my maxima... – nbro Mar 30 '15 at 16:37
  • @Rinzler I'm not sure I understand what you want. It sounds like using `fpprec` and `bfloat` is what you want, since you want results that have varying precision, and ordinary floats have fixed precision. But maybe you can say more about what you are trying to achieve. – Robert Dodier Mar 30 '15 at 16:40
3

One option is to define

decimal_places(ex,n):=parse_string(printf(false,sconcat("~,",n,"f"),ex));

E.g.

decimal_places(22/7,4);

But, beware of numerical rounding (internal) caused by representing decimal numbers as binary floats.

E.g.

printf(false,"~,1f",1.45);

returns 1.4

printf(false,"~,3f",0.0145);

returns 0.015.

This is not bankers' rounding either (which "round" does by the way... Compare round(1.5); with round(2.5);).

Axel
  • 3,331
  • 11
  • 35
  • 58
  • This turned out to be trickier than I thought at first glance ... anyway a definition of the decimal places function which doesn't involve string operations is this: `dp(e, n) := block([m], m: ceiling (log(float(e))/log(10.0)), float(e)*10^(n - m), round(%%), %%*10.0^(m - n))`. E.g. `dp(%e, 3)` => 2.72, `dp(1000*%e, 3)` => 2720.0, `dp(%e/1000, 3)` => 0.00272. – Robert Dodier May 27 '19 at 03:01
  • A couple of comments about `decimal_places` as shown above. (1) One can indicate a variable precision in the output of printf by using `v` in the `~f` formatter, e.g. `printf(true, "~,vf~%", 4, 1.234567)` outputs 1.2346. (2) The rounding performed for `~f` format isn't well-defined for inputs ending in `5`. Maxima `printf` punts to Common Lisp FORMAT, and the CL spec says that the rounding for inputs ending in `5` can be rounded up or rounded down -- it is left to the Lisp implementation. This is, I believe, an unfortunate deficiency in the spec. – Robert Dodier May 27 '19 at 03:07
3
rnddp(x,dp):=float((round(x*10^dp)/10^dp));

rndcdp(z,dp):=rnddp(realpart(z),dp)+%i*rnddp(imagpart(z),dp);

rnddp will round its first argument to the number of decimal places provided in the second argument.

rndcdp does the same for complex numbers.

The result(s) are the approximated values, not just displayed values.

StardustGogeta
  • 3,331
  • 2
  • 18
  • 32
peter 124
  • 31
  • 1
2

I have not found a way to approximate a number using float, but I found a way of approximating using bfloat.

From the official documentation:

bfloat (expr)

Converts all numbers and functions of numbers in expr to bigfloat numbers. The number of significant digits in the resulting bigfloats is specified by the global variable fpprec.

Thus, I can achieve more or less what I wanted by using something like this:

bfloat(%e), fpprec:4;

And the output is:

2.718b0

If someone knows how to do it using the float function, please post it.

nbro
  • 15,395
  • 32
  • 113
  • 196
0

x:3.14159;

x:x*10000;

x:floor(x+0.5);

x:x/10000;

float(x);

"3.1416"

Alan Getz
  • 1
  • 1
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 09 '22 at 02:15