Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I need a formatting function (say format[x_, n_]) which outputs numbers with fixed n significant digits without unnecessary dot. Examples:

format[.02,3] -> "0.0200"
format[.2,3] -> "0.200"
format[1,3] -> "1.00"
format[100,3] -> "100"    
format[1000,3] -> "100\[Times]10^1"
format[10000,3] -> "100\[Times]10^2"

Any ideas? The shorter - the simpler!

share|improve this question

5 Answers 5

You probably need to read tutorial Output Formats for Numbers, but long story short, you are looking for NumberForm

NumberForm[N[Pi], 10]

3.141592654

Main thing is controlling number of precise digits and the number of digits to the right of the decimal:

NumberForm[1.23456, {3, 4}]

1.2300

Cool things you can also do:

NumberForm[30!, DigitBlock -> 5, NumberSeparator -> " "]

265 25285 98121 91058 63630 84800 00000

NumberForm[1234567890., 10, ExponentStep -> 6, NumberMultiplier -> "*"]

enter image description here

share|improve this answer

It's not so easy to achieve your goal, because NumberForm always wants a number n of digits to precision or a pair {totaldigits, digits-after-decimal-point}. So we must use PaddingForm or Row to do it. The solution isn't very short then. But the following code seems to work:

Clear[format]
Options[format] = Options[NumberForm];
format[x_, sd_] := 
 Module[{m, e, man, exp, num, n, f}, {m, e} = MantissaExponent[x];
  If[Abs[x] <= 10^-sd,
   Row[{PaddedForm[10 m, {sd, sd - 1}], Superscript["\[Times]10", e - sd + 2]}],
   If[e < sd,
    n = sd - e - 1; f = sd - e;
    If[n == 0, PaddedForm[x, {sd, f}], PaddedForm[x, {n, f}]], 
    If[sd == e, PaddedForm[x, sd],(*else sd<e*)
     Row[{Round[10^sd m, 10^-sd], 
       Superscript["\[Times]10", e - sd]}]]]]]    

For your examples you will get

Mathematica graphics

Update
Replacing the Numberform, in If[n==0,...] with PaddedForm[x,{sd,f}] seems to work for the cases, which the old routine failed, as Alexey Popkov mentioned in his comment.

Update 2

Seems to work now for numbers smaller than 10^-sd.

share|improve this answer
    
Thank you. But for some cases your function still gives wrong result: format[10, 3] gives 10 instead of 10.0. –  Alexey Popkov Aug 1 '12 at 12:19
    
Another case: format[.00000002, 3] should give "2.00\[Times]10^-8". –  Alexey Popkov Aug 1 '12 at 12:32
    
@AlexeyPopkov This case seems to work now after Update 2. –  Peter Breitfeld Aug 1 '12 at 13:28

in a similar case I used a combination of NumberForm and AccountingForm

ie:

AccountingForm[NumberForm[fn[i, j], {16, 16}]]

to get 16 digits

I get this:

0.0681758870688004

instead of this:

0.0681759

share|improve this answer
up vote 7 down vote accepted

Here I present the scientific formatting function I have developed. It allows to restrict the displayed digits to only precise digits (negative and zero precision are also supported) and to specify the maximum number of zeros after the decimal point before converting the number to exponential form (negative values of this option are interpreted as the minimum number of digits before decimal point which will be showed). The option PadSign controls sign padding for positive numbers. The option Align allows to specify where the \[AlignmentMarker] should be placed inside of the number: before decimal point ("."), before first significant digit of the number ("FirstDigit") or it should not be included in the output (any other value). The output is always wrapped in Item and the option Alignment->"\[AlignmentMarker]" is set when the Align is not switched off. It is also possible to pass any options of Item through SciForm.

Here is a demonstration of what is possible with SciForm (the code for generating this table see at bottom of this post): table1

The code of SciForm:

ClearAll[SciForm];
Options[SciForm]=Join[Options[Item],{Align->"FirstDigit",PadSign->False}];
SyntaxInformation[SciForm]={"ArgumentsPattern"->{_,_.,OptionsPattern[]}};
SciForm::"sigz"= "In addition to `1` precise digit`3` requested, `2` zero`4` will appear as placeholder`4`.";
SciForm[x_?NumericQ,prec_Integer,thr_Integer:4,opts:OptionsPattern[]]:=
   Module[{rd,e=MantissaExponent[x][[2]],m1,m2,sign,mess,exp,i,al,alF},
      rd=If[prec>0,ToString/@RealDigits[Round[x,10^(-prec+e)],10,prec][[1]],{}];
      sign=If[Negative[x],"-",If[TrueQ@OptionValue[PadSign],ToString[Invisible["+"],StandardForm],""]];
      If[Head[alF=al=OptionValue[Align]]===List,al=First@alF;alF={"\[AlignmentMarker]",alF[[2]]},alF={"\[AlignmentMarker]",Center}];
      m1=If[TrueQ[al==="FirstDigit"],"\[AlignmentMarker]",""];
      m2=If[TrueQ[al==="."],"\[AlignmentMarker]",""];
      i=If[TrueQ[MatchQ[al,"."|"FirstDigit"]],
             Item[#,Alignment->alF,FilterRules[{opts},Options[Item]]]&,Item[#,FilterRules[{opts},Options[Item]]]&];
      exp[n_]:=ToString[Superscript["10",n],StandardForm];
      mess:=Message[SciForm::"sigz",prec,-thr-prec,If[prec>1,"s",""],If[-thr-prec>1,"s",""]];
      i@Which[
         e!=prec<=0,StringJoin[sign,m1,"0",m2,".?*",exp[e-prec]],
         e==prec<=0,StringJoin[sign,m1,"0",m2,".?"],
         0==e>=-thr,StringJoin[sign,"0",m2,".",m1,rd],
         0>e>=-thr,StringJoin[sign,"0",m2,".",Array["0"&,-e],m1,rd],
         0>=-thr>e,StringJoin[sign,"0",m2,".",m1,rd,"*",exp[e]],
         1<=-thr>e&&-thr<prec>=1,StringJoin[sign,m1,Insert[rd,{m2,"."},1-thr],"*",exp[e+thr]],
         1<=-thr==prec>e,StringJoin[sign,m1,rd,m2,"*",exp[e+thr]],
         1<=-thr>prec>e,mess;StringJoin[sign,m1,rd,Array["0"&,-thr-prec],m2,"*",exp[e+thr]],
         prec>e>0,StringJoin[sign,m1,Insert[rd,{m2,"."},e+1]],
         prec==e>0&&-thr<=prec,StringJoin[sign,m1,rd,m2],
         e==-thr>prec>0,mess;StringJoin[sign,m1,rd,Array["0"&,-thr-prec],m2],
         e>prec>0&&-thr<=prec,StringJoin[sign,m1,rd,m2,"*",exp[e-prec]],
         e>=prec>0&&-thr>prec,mess;StringJoin[sign,m1,rd,Array["0"&,-thr-prec],m2,"*",exp[e+thr]]
]];

The code for the above table:

data = {.0000000123456789, .000000123456789, -.00000123456789, \
-.0000123456789, .000123456789, .00123456789, .0123456789, .123456789,
    1.23456789, 12.3456789, 123.456789, 1234.56789, 12345.6789, 
   123456.789};
(*Note that NumberForm does not print Message although when called as \
NumberForm[123456.789,5] it does. Is it a bug? *)
Grid[Prepend[
  {SciForm[#, 4
      , Align -> "."
      , BaseStyle ->
       FontFamily -> "Times"],
     SciForm[#, 4, 5
      , BaseStyle ->
       FontFamily -> "Times"],
     SciForm[#, 4, -4
      , BaseStyle ->
       FontFamily -> "Times"],
     SciForm[#, 4, -1
      , BaseStyle ->
       FontFamily -> "Times"]} & /@ data,
  Item[#, Alignment -> "\[AlignmentMarker]", 
     BaseStyle -> {10, Bold}] & /@ {
    "SciForm[\[AlignmentMarker]#,4\[IndentingNewLine],Align\[Rule]\".\
\"\[IndentingNewLine],BaseStyle\[Rule]\[IndentingNewLine]FontFamily\
\[Rule]\"Times\"]&",
    "SciForm[#\[AlignmentMarker],4,5\[IndentingNewLine],Align\[Rule]\"\
FirstDigit\"\[IndentingNewLine],BaseStyle\[Rule]\[IndentingNewLine]\
FontFamily\[Rule]\"Times\"]&",
    "SciFor\[AlignmentMarker]m[#,4,-4\[IndentingNewLine],Align\[Rule]\
\"FirstDigit\"\[IndentingNewLine],BaseStyle\[Rule]\[IndentingNewLine]\
FontFamily\[Rule]\"Times\"]&",
    "SciFor\[AlignmentMarker]m[#,4,-1\[IndentingNewLine],Align\[Rule]\
\"FirstDigit\"\[IndentingNewLine],BaseStyle\[Rule]\[IndentingNewLine]\
FontFamily\[Rule]\"Times\"]&"}
  ], Frame -> All, Alignment -> {Automatic, Center}]

Any ideas and suggestions are welcome!

share|improve this answer
1  
Maybe you will find interesting this related Q&A –  Kuba Aug 2 '13 at 12:00

mestLevo[x_] := Last[RealDigits[N[x]]];

SigMest[x_, n_] := If[n == 0, Round[x] // N, Round[x 10^-mestLevo[x] 10^n] 10^-n 10^mestLevo[x]] // N;

share|improve this answer
1  
Unfortunately, this does not produce the required output as described in the question. –  Sjoerd C. de Vries Apr 9 at 17:23

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.