Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

NumberSigns and Number Formatting

1 view
Skip to first unread message

David Park

unread,
Oct 9, 2008, 6:37:39 AM10/9/08
to
I would like to write numbers in a dynamic display such that as the numbers
are varied the width and positioning of the digits, fill spaces, and signs
remained fixed. Now I know that I can do this if I pick a monspace font such
as Courier. However, I would like to do this within Panels and in general
with proportional fonts. The font that is used within Panels is given by
evaluating CurrentValue["PanelFontFamily"] and gives "Segoe UI". It's a nice
looking font and I'm happy with it. I don't want a different font for text
and numbers in a display.

I assume that with proportional fonts the widths of all the digit characters
are the same. The problem is that the space character is much thinner than
the digits, and + and - are also different widths than the digits. I found
that for NumberPadding on the left I could sometimes use \[LetterSpace] to
match the width of the digits, but I don't think this works for all fonts or
font sizes. Also it leaves a slight trace of its presence, which would be
nice to eliminate.

Here is a test case to experiment with:

Module[
{x = 0., numformat},
numformat[x_] :=
NumberForm[N[x], {6, 3}, NumberPadding -> {"\[LetterSpace]", "0"},
NumberSigns -> {"-", "\[LetterSpace]"}, SignPadding -> False];
Panel[
Column[
{Row[{-15 <= "x" <= 15, Spacer[5],
Slider[Dynamic[x], {-15, 15, .001}], Spacer[5],
InputField[Dynamic[x], FieldSize -> {5, 1.2}]}],
Row[{"x:", Spacer[5], Dynamic@numformat[x], Spacer[5],
"in value."}]
}],
Style["Number Formatting Problem", 16],
BaseStyle -> {FontSize -> 16}]
]

For a FontSize of 16 the LetterSpace works well for the NumberPadding but it
does not work well enough for the NumberSigns. If the FontSize is changed to
12 then it doesn't work for either. If you vary the slider you will see a
fair amount of jumping around.

The basic problem here is that NumberPadding and NumberSigns take only
single character strings. The ideal solution would be if one could use:

NumberPadding -> {Invisible["0"], "0"}
NumberSigns -> {"-", Invisible["-"]}

but that is not possible.

Unless someone can suggest a reasonable solution to this maybe it's time
that WRI considered updating NumberFormat.

--
David Park
djm...@comcast.net
http://home.comcast.net/~djmpark/

Albert Retey

unread,
Oct 10, 2008, 4:39:27 AM10/10/08
to

I think your problem is that you are trying at the wrong place.
NumberForm is for constructing a string representation of a number, it
doesn't care how the string is represented on screen (or paper). To do
that there are other functions. I think the following should have the
properties you are seeking for and should work with any font you choose
(for some you might need to adapt the ImageSize of the Pane)

Module[{x = 0., numformat},

numformat[x_] :=
NumberForm[N[x], {6, 3}, NumberPadding -> {"", "0"},
NumberSigns -> {"-", " "}, SignPadding -> False];
DynamicModule[{fs = 10},
Dynamic@Panel[Column[
{
PopupMenu[Dynamic[fs], {10, 12, 14, 16, 18, 20, 22}],


Row[{-15 <= "x" <= 15, Spacer[5],
Slider[Dynamic[x], {-15, 15, .001}], Spacer[5],
InputField[Dynamic[x], FieldSize -> {5, 1.2}]}],
Row[{"x:", Spacer[5],

Pane[Dynamic[
numformat[x]
], ImageSize -> Dynamic[Round[{4*fs, fs}]],
Alignment -> {Right, Baseline}],


Spacer[5], "in value."}]
}],
Style["Number Formatting Problem", 16],

BaseStyle -> {FontSize -> fs}]
]
]

> Unless someone can suggest a reasonable solution to this maybe it's time
> that WRI considered updating NumberFormat.

I don't think that WRI would agree that NumberFormat has a problem...

hth,

albert

David Park

unread,
Oct 11, 2008, 6:45:20 AM10/11/08
to
Thank you Albert for your reply. Your suggestion of using a Pane and right
alignment to obviate the proportional font problem works.

I believe that NumberForm was originally designed for monospace fonts. This
was generally good enough. The Help for NumberForm says that it controls how
the number 'prints' and not that it's purpose is to convert the number to a
string. In any case, now that we have much easier dynamics, and constructs
like Panel with its proportional font (which I like), there will be much
more formatting of numbers within lines of text. NumberForm no longer works
properly for this purpose. We can end up getting a lot of 'jitter'. If
somehow we could pad with blank characters that had the same widths as "-"
and "0" in the font then that would be the simplest solution. If that
solution could be implemented within NumberForm (and maybe it is impossible)
the average user would find it relatively easy to use. The solution you give
is slightly heavy lifting for most users. Just because a solution is
possible doesn't mean that it will be readily available to most users. They
are going to spend a lot of time looking at NumberPadding and NumberSigns
because that is the obvious indicated path.

In any case, here is a routine, starting with your suggestions, for
formatting proportional font numbers in lines of text.

NumberFormPane::usage =
"NumberFormPane[number,digitspecs,imagesize,opts] will display a \
number formatted with NumberForm within a Pane with the given \
imagesize. Options for both Pane and NumberForm may be given. By \
default the number is displayed right justified in the Pane and with \
the Baseline aligned with the surrounding Baseline. This allows \
numbers, even with proportional fonts, to be displayed in a fixed \
position within lines of text.";
Options[NumberFormPane] =
Join[Options[NumberForm],
FilterRules[Options[Pane], Except[ImageSize]]];
NumberFormPane[number_?NumericQ, digitspecs_, imagesize_,
opts : OptionsPattern[]] :=
Pane[NumberForm[number, digitspecs,
FilterRules[{opts}, Options[NumberForm]]], ImageSize -> imagesize,
Sequence[FilterRules[{opts}, Options[Pane]]],


Alignment -> {Right, Baseline},

BaselinePosition -> Baseline,
ImageSizeAction -> "ShrinkToFit"]

Here is one test:

Module[
{x = 0., fs = 16},


Panel[
Column[
{Row[{-15 <= "x" <= 15, Spacer[5],
Slider[Dynamic[x], {-15, 15, .001}], Spacer[5],
InputField[Dynamic[x], FieldSize -> {5, 1.2}]}],

Row[{"x variable:", Spacer[5],
Dynamic@NumberFormPane[x, {6, 3}, Round[{4 fs, fs}]],


Spacer[5], "in value."}]
}],
Style["Number Formatting Problem", 16],
BaseStyle -> {FontSize -> fs}]
]

The following is an example where not enough space has been left for the
length of the number with larger negative values. Then ShrinkToFit is used.

Module[
{x = 0., fs = 16},


Panel[
Column[
{Row[{-15 <= "x" <= 15, Spacer[5],
Slider[Dynamic[x], {-15, 15, .001}], Spacer[5],
InputField[Dynamic[x], FieldSize -> {5, 1.2}]}],

Row[{"x variable:", Spacer[5],
Dynamic@NumberFormPane[x, {6, 3}, {50, 16}],


Spacer[5], "in value."}]
}],
Style["Number Formatting Problem", 16],

BaseStyle -> {FontSize -> fs},
ImageSize -> {500, 80}]
]

Without specifying the ImageSize for the Panel, we would get some jumping of
the Panel height. So there is still a certain amount of diddling and that is
why being able to pad with proper width spaces would be an easier solution.


"Albert Retey" <aw...@gmx-topmail.de> wrote in message
news:gcn4bv$76e$1...@smc.vnet.net...

Bob Hanlon

unread,
Oct 11, 2008, 6:53:05 AM10/11/08
to
On my system

$Version

6.0 for Mac OS X PowerPC (32-bit) (June 19, 2007)

the display would not show numbers smaller than -9.999 because there was insufficient space for the number. It worked as expected when I changed Round[{4*fs, fs}] to Round[{4.2*fs, fs}]

Bob Hanlon


Module[{x = 0., numformat},
numformat[x_] :=
NumberForm[N[x], {6, 3}, NumberPadding -> {"", "0"},
NumberSigns -> {"-", " "}, SignPadding -> False];
DynamicModule[{fs = 10},
Dynamic@Panel[
Column[{PopupMenu[Dynamic[fs], {10, 12, 14, 16, 18, 20, 22}],
Row[{-15 <= "x" <= 15, Spacer[5],
Slider[Dynamic[x], {-15, 15, .001}], Spacer[5],
InputField[Dynamic[x], FieldSize -> {5, 1.2}]}],
Row[{"x:", Spacer[5],
Pane[Dynamic[numformat[x]],

ImageSize -> Dynamic[Round[{4.2*fs, fs}]],

Alignment -> {Right, Baseline}], Spacer[5], "in value."}]}],
Style["Number Formatting Problem", 16],
BaseStyle -> {FontSize -> fs}]]]

---- Albert Retey <aw...@gmx-topmail.de> wrote:

=============

hth,

albert


--

Bob Hanlon


Albert Retey

unread,
Oct 13, 2008, 7:05:53 AM10/13/08
to
Hi,

> I believe that NumberForm was originally designed for monospace fonts. This
> was generally good enough. The Help for NumberForm says that it controls how
> the number 'prints' and not that it's purpose is to convert the number to a
> string.

Sorry, I didn't even look up the help for NumberForm, which obviously
was a mistake: Of course saying it is for converting to string strictly
speaking was nonsense, since it actually doesn't even do that. What I
probably should have said is that I think its purpose is to create a
sequence of characters to be shown.

> In any case, now that we have much easier dynamics, and constructs
> like Panel with its proportional font (which I like), there will be much
> more formatting of numbers within lines of text. NumberForm no longer works
> properly for this purpose.

correct

> We can end up getting a lot of 'jitter'. If
> somehow we could pad with blank characters that had the same widths as "-"
> and "0" in the font then that would be the simplest solution.

Hm, I'm not an expert for proportional fonts, but naive as I am I would
believe this probably isn't possible in general, are there any
(technical) rules that for a proportial font all digits have to be the
same size (and height)? Is a blank character with the correct size
something that WRI can provide for any font that you can install and use
within a mathematica document? I don't know. If not, even without
padding a jitter wouldn't be to avoid...

> If that solution could be implemented within NumberForm (and maybe it is impossible)
> the average user would find it relatively easy to use. The solution you give
> is slightly heavy lifting for most users. Just because a solution is
> possible doesn't mean that it will be readily available to most users. They
> are going to spend a lot of time looking at NumberPadding and NumberSigns
> because that is the obvious indicated path.

That's correct, it could be made easier and be explained better in the
documentation. If there would be a NumberFormPane as the one you suggest
and that would be mentioned in the "See Also" section that would be
probably the best solution. I think for WRI it pobably would even be
possible to automatically determine the correct Pane-Size with more
internal knowledge about the font-properties, so that the Pane-Size
would only need to change when the font would be changed, but not when
only the content changes. But I'm not sure and unfortunatly I can't
provide that :-). Actually it would be interesting to know if and how
other systems / programming languages / GUI toolkits handle this.

Finally I have another workaround, more along the lines you originally
suggested that should work for most cases. It just makes strings from
NumberForm, and then replaces the string with a row where invisible
padding characters are written using Style[_,Opacity[0]]:

Module[{x = 0., numformat}, numformat[x_] := Row[
List @@
StringReplace[
ToString[
NumberForm[N[x], {6, 3}, NumberPadding -> {"@", "0"},
NumberSigns -> {"-", "$"}, SignPadding -> False]], {
"@" -> Style["0", Opacity[0]], "$" -> Style["-", Opacity[0]]
}
]];


Panel[Column[{Row[{-15 <= "x" <= 15, Spacer[5],
Slider[Dynamic[x], {-15, 15, .001}], Spacer[5],
InputField[Dynamic[x], FieldSize -> {5, 1.2}]}],
Row[{"x:", Spacer[5], Dynamic@numformat[x], Spacer[5],
"in value."}]}], Style["Number Formatting Problem", 16],
BaseStyle -> {FontSize -> 16}]]


cheers,

albert

0 new messages