Undocumented Matlab
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT

Formatting numbers

August 24, 2011 7 Comments

We often need to display numbers, in GUI, text files or maybe the console window (Matlab Desktop). Matlab has built-in support for this using the fully-documented num2str, sprintf and format functions. Unfortunately, these built-in functions, useful as they are for simple needs, have several limitations:

  • They do not take into account the user’s computer Locale settings. For example, the number 1234.56 is normally displayed as 1,234.56 or 1’234.56 or 1234,56 depending on your chosen Locale (which is determined by the local language and country). The functions always use the same manner to display the number, disregarding the user’s Locale.
  • format does not enable customization of the number of decimal digits, and num2str and sprintf‘s ability to do so is limited. Customization of the decimal sign and thousands grouping sign is even more difficult.

I have recently completed a consulting work for a bank in Switzerland where these limitations were very important. The bank has branches in several countries and people naturally use different Locales on their computer. Moreover, some data values (for example, FOREX exchange rates) need more than two decimal digits. I had to find a generic cross-platform way to code this in Matlab in a way that will work for all users out-of-the-box (the application is compiled and distributed as an executable).
The solution was to use Matlab’s fully-documented built-in support for using Java objects. In this case, we shall use the standard java.text.DecimalFormat:

>> % Simple formatting example
>> nf = java.text.DecimalFormat
>> nf.format(1234567.890123)
ans =
1,234,567.89
>> % Modify some properties...
>> set(nf,'GroupingSize',5)
>> nf.setMaximumFractionDigits(4)
>> nf.format(1234567.890123)
ans =
12,34567.8901

>> % Simple formatting example >> nf = java.text.DecimalFormat >> nf.format(1234567.890123) ans = 1,234,567.89 >> % Modify some properties... >> set(nf,'GroupingSize',5) >> nf.setMaximumFractionDigits(4) >> nf.format(1234567.890123) ans = 12,34567.8901

In the simple code snippet above, note the two alternative manners in which I set the DecimalFormat object’s properties, once with the set(‘XYZ’,value) function, then using the corresponding Java accessor method setXYZ(value). In most cases, we find that Java properties can be set using either of these manners, although using the Java accessor methods is typically safer and prevents some possible problems. Similarly, property values can be retrieved using either get(‘XYZ’) or the corresponding getXYZ() or isXYZ() Java methods (which are better).
Some of the interesting gettable/settable properties of the DecimalFormat object include (my Locale’s defaults are specified – your Locale might be different):

  • Currency – a java.util.Currency object that sets the currency symbol, international currency code and number of fractional decimal digits
  • DecimalFormatSymbols – a java.text.DecimalFormatSymbols object that sets the character symbols for such things as the decimal sign (“.” or “,” for example), grouping separator (“,” or ” ‘ ” or whatever), percent and per-mill signs, minus sign, infinity sign etc.
  • DecimalSeparatorAlwaysShown – (default=false) a boolean flag that specifies whether or not to display the decimal sign even for integer numbers. For example, “123.” rather than “123”.
  • GroupingSize – (default=3) indicates how many integer digits should be grouped by the grouping (“thousands”) separator sign.
  • GroupingUsed – (default=true) a boolean flag that specifies whether or not to use the grouping sign at all. Matlab’s built-in num2str does not use grouping.
  • MaximumFractionDigits – (default=3) the maximal number of digits to display to the right of the decimal sign. Post-rounding trailing zeros are omitted.
  • MinimumFractionDigits – (default=0) the minimum number of digits to display, padding with trailing zeros if necessary.
  • MaximumIntegerDigits – (default=intmax) the maximal number of digits to display to the left of the decimal sign. Extra digits are removed.
  • MinimumIntegerDigits – (default=1) the minimum number of digits to display, padding with leading zeros if necessary.
  • Multiplier – (default=1) multiplies the number by the specified value before converting to string.
  • NegativePrefix – (default=’-‘) the string to display to the left of a negative number.
  • NegativeSuffix – default = ”) the string to display to the right of a negative number. Some bankers like to display negative numbers as “(value)” and this is easy to do using NegativePrefix and NegativeSuffix. There are corresponding properties PositivePrefix and PositiveSuffix.
  • RoundingMode – (default=RoundingMode.HALF_EVEN) a java.math.RoundingMode object that sets the manner in which numbers are rounded to fit the required number of digits.

In addition, the DecimalFormat object provides methods that enable setting/getting a pattern that directly specifies how numbers should be parsed. A description of the different pattern components can be found here. The pattern directly corresponds to the settable properties listed above, and is very similar to the custom numeric pattern that is settable in Microsoft Excel. For example:

>> % default format:
>> nf.toPattern
ans =
#,##0.###
>> str = char(nf.format(-pi))
str =
-3.142
>> % non-default format:
>> nf.setNegativePrefix('- (')
>> nf.setNegativeSuffix(') !!!')
>> % alternatively: nf.applyPattern('#,##0.###;- (#,##0.###) !!!')
>> nf.toPattern
ans =
#,##0.###;- (#,##0.###) !!!
>> str = nf.format(-pi).char
str =
- (3.142) !!!
>> % Alternatively, we could use the pattern directly:
>> str = char(java.text.DecimalFormat('#,##0.###;- (#,##0.###) !!!').format(-pi));

>> % default format: >> nf.toPattern ans = #,##0.### >> str = char(nf.format(-pi)) str = -3.142 >> % non-default format: >> nf.setNegativePrefix('- (') >> nf.setNegativeSuffix(') !!!') >> % alternatively: nf.applyPattern('#,##0.###;- (#,##0.###) !!!') >> nf.toPattern ans = #,##0.###;- (#,##0.###) !!! >> str = nf.format(-pi).char str = - (3.142) !!! >> % Alternatively, we could use the pattern directly: >> str = char(java.text.DecimalFormat('#,##0.###;- (#,##0.###) !!!').format(-pi));

Note how we convert the java.lang.String object returned by the format method into a Matlab string using the built-in char function.
To test how the numbers react to different Locales, we could specify a specific Locale to the DecimalFormatSymbols object, as follows:

>> dfs = java.text.DecimalFormatSymbols(java.util.Locale('fr-CH'));  % Swiss-French Locale
>> dfs.setGroupingSeparator('''');  % use ' rather than ,
>> nf.setDecimalFormatSymbols(dfs)
>> nf.format(123456.789012)
ans =
123'456.789

>> dfs = java.text.DecimalFormatSymbols(java.util.Locale('fr-CH')); % Swiss-French Locale >> dfs.setGroupingSeparator(''''); % use ' rather than , >> nf.setDecimalFormatSymbols(dfs) >> nf.format(123456.789012) ans = 123'456.789

Alternatively, change the computer’s current Locale (in Windows, this is done via the Control Panel’s Regional Settings dialog), open a new Matlab session and rerun the code using the default DecimalFormat. Restarting Matlab is important, because the Locale is only read once by the Java engine (JVM), when it starts, and this happens when Matlab starts.

Window's Control Panel's Regional Settings Locale
Window's Control Panel's Regional Settings Locale

To complete the picture, the DecimalFormat object can not only format a numeric value as a string, using format() as we have seen above, but also the reverse – convert a string to a numeric value using parse():

>> value = nf.parse('123''456.789').doubleValue
value =
                123456.789

>> value = nf.parse('123''456.789').doubleValue value = 123456.789

Related posts:

  1. GUI formatting using HTML – HTML formatting an be used to align and background-color text within Matlab uicontrols such as buttons, listboxes, uitables etc. ...
  2. Matlab toolstrip – part 6 (complex controls) – Multiple types of customizable controls can be added to Matlab toolstrips...
  3. Editbox data input validation – Undocumented features of Matlab editbox uicontrols enable immediate user-input data validation...
  4. Types of undocumented Matlab aspects – This article lists the different types of undocumented/unsupported/hidden aspects in Matlab...
  5. Setting axes tick labels format – Matlab plot axes ticks can be customized in a way that will automatically update whenever the tick values change. ...
  6. Reading non-Latin text files – A workaround that enables reading non-Latin text files in Matlab is shown...
Java
Print Print
« Previous
Next »
7 Responses
  1. Mikhail August 29, 2011 at 02:04 Reply

    Do you have a solution to format doubles leaving n (say 4) significant digits for pos/neg numbers between for example [1e-5, 1e+5] and scientific notation for very large/small numbers like in example below?

    0.000012345678 -> 1.235e-005
    0.001234567898 -> 0.001235
    0.123456789876 -> 0.1235
    1.234567898765 -> 1.235
    123.4567898765 -> 123.5
    1234.567898765 -> 1235
    123456.7898765 -> 123457
    1234567.898765 -> 1.234e+006

    • Donn Shull August 29, 2011 at 08:35 Reply

      except for your next to last example you could use the sprintf option as follows:

      for index = [0,2,4,5,7,8,10,11], disp(sprintf('%6.4g', 0.000012345678*10^index)); end
      1.235e-005
      0.001235
      0.1235
      1.235
      123.5
      1235
      1.235e+005
      1.235e+006

      for index = [0,2,4,5,7,8,10,11], disp(sprintf('%6.4g', 0.000012345678*10^index)); end 1.235e-005 0.001235 0.1235 1.235 123.5 1235 1.235e+005 1.235e+006

      perhaps there are other solutions.

      Donn

  2. Grouping Digits | Now January 19, 2014 at 22:03 Reply

    […] I don’t have to face this issue in the context of international banking, like what he had (https://undocumentedmatlab.com/blog/formatting-numbers/). So I’m particularly grateful that the expert has written a *simple* article to illustrate […]

  3. Ori August 12, 2014 at 00:30 Reply

    Is there also a way to force a specific scientific notation power?

    For example instead of Matlab displaying:

    0.001e-3

    Make it show 1.123e-6 ?

    This is important sometimes when small numbers are part of a vector with larger values.

    Thanks,

    Ori

    • Yair Altman August 12, 2014 at 01:22 Reply

      @Ori – you need to do it programmatically, there is no immediate solution for displaying a vector with different exponents.

  4. Collin April 5, 2016 at 12:20 Reply

    I need to format numbers with engineeering prefixes 1e3 to 1k, sometimes with units (1 kg).

    Currently,I use DecimalFormat with the right prefix to get the exponent into groups of 3, than native matlab string handling and a hashtable to extract the correct prefic (exponent ‘3’ = ‘k’), all well and good. The FEX submission, num2sip (http://www.mathworks.com/matlabcentral/fileexchange/33174-number-to-scientific-prefix) does the same thing cleverer and all in native matlab.

    My question is the use of a AttributedCharacterIterator and the attribute returned. The attribute returned is a java.text.NumberFormat.Field object but takes the form java.text.NumberFormat$Field(exponent field) and I can not seem to create a java.text.NumberFormat.Field object in matlab.

    Any help would be appreciated

    • Yair Altman April 5, 2016 at 18:49 Reply

      @Collin –

      sysClassLoader = java.lang.ClassLoader.getSystemClassLoader();
      FieldClass = sysClassLoader.loadClass('java.text.NumberFormat$Field');
      exponentField = FieldClass.getField('CURRENCY').get([]);

      sysClassLoader = java.lang.ClassLoader.getSystemClassLoader(); FieldClass = sysClassLoader.loadClass('java.text.NumberFormat$Field'); exponentField = FieldClass.getField('CURRENCY').get([]);

Leave a Reply
HTML tags such as <b> or <i> are accepted.
Wrap code fragments inside <pre lang="matlab"> tags, like this:
<pre lang="matlab">
a = magic(3);
disp(sum(a))
</pre>
I reserve the right to edit/delete comments (read the site policies).
Not all comments will be answered. You can always email me (altmany at gmail) for private consulting.

Click here to cancel reply.

Useful links
  •  Email Yair Altman
  •  Subscribe to new posts (feed)
  •  Subscribe to new posts (reader)
  •  Subscribe to comments (feed)
 
Accelerating MATLAB Performance book
Recent Posts

Speeding-up builtin Matlab functions – part 3

Improving graphics interactivity

Interesting Matlab puzzle – analysis

Interesting Matlab puzzle

Undocumented plot marker types

Matlab toolstrip – part 9 (popup figures)

Matlab toolstrip – part 8 (galleries)

Matlab toolstrip – part 7 (selection controls)

Matlab toolstrip – part 6 (complex controls)

Matlab toolstrip – part 5 (icons)

Matlab toolstrip – part 4 (control customization)

Reverting axes controls in figure toolbar

Matlab toolstrip – part 3 (basic customization)

Matlab toolstrip – part 2 (ToolGroup App)

Matlab toolstrip – part 1

Categories
  • Desktop (45)
  • Figure window (59)
  • Guest bloggers (65)
  • GUI (165)
  • Handle graphics (84)
  • Hidden property (42)
  • Icons (15)
  • Java (174)
  • Listeners (22)
  • Memory (16)
  • Mex (13)
  • Presumed future risk (394)
    • High risk of breaking in future versions (100)
    • Low risk of breaking in future versions (160)
    • Medium risk of breaking in future versions (136)
  • Public presentation (6)
  • Semi-documented feature (10)
  • Semi-documented function (35)
  • Stock Matlab function (140)
  • Toolbox (10)
  • UI controls (52)
  • Uncategorized (13)
  • Undocumented feature (217)
  • Undocumented function (37)
Tags
ActiveX (6) AppDesigner (9) Callbacks (31) Compiler (10) Desktop (38) Donn Shull (10) Editor (8) Figure (19) FindJObj (27) GUI (141) GUIDE (8) Handle graphics (78) HG2 (34) Hidden property (51) HTML (26) Icons (9) Internal component (39) Java (178) JavaFrame (20) JIDE (19) JMI (8) Listener (17) Malcolm Lidierth (8) MCOS (11) Memory (13) Menubar (9) Mex (14) Optical illusion (11) Performance (78) Profiler (9) Pure Matlab (187) schema (7) schema.class (8) schema.prop (18) Semi-documented feature (6) Semi-documented function (33) Toolbar (14) Toolstrip (13) uicontrol (37) uifigure (8) UIInspect (12) uitools (20) Undocumented feature (187) Undocumented function (37) Undocumented property (20)
Recent Comments
  • Nicholas (6 days 12 hours ago): Hi Yair, Thanks for the reply. I am on Windows 10. I also forgot to mention that this all works wonderfully out of the editor. It only fails once compiled. So, yes, I have tried a...
  • Nicholas (6 days 12 hours ago): Hi Yair, Thanks for the reply. I am on Windows 10. I also forgot to mention that this all works wonderfully out of the editor. It only fails once compiled. So, yes, I have tried a...
  • Yair Altman (6 days 20 hours ago): Nicholas – yes, I used it in a compiled Windows app using R2022b (no update). You didn’t specify the Matlab code location that threw the error so I can’t help...
  • Nicholas (7 days 16 hours ago): Hi Yair, Have you attempted your displayWebPage utility (or the LightweightHelpPanel in general) within a compiled application? It appears to fail in apps derived from both R2022b...
  • João Neves (10 days 21 hours ago): I am on matlab 2021a, this still works: url = struct(struct(struct(struct(hF ig).Controller).PlatformHost). CEF).URL; but the html document is empty. Is there still a way to do...
  • Yair Altman (13 days 19 hours ago): Perhaps the class() function could assist you. Or maybe just wrap different access methods in a try-catch so that if one method fails you could access the data using another...
  • Jeroen Boschma (13 days 22 hours ago): Never mind, the new UI components have an HTML panel available. Works for me…
  • Alexandre (13 days 23 hours ago): Hi, Is there a way to test if data dictionnatry entry are signal, simulink parameters, variables … I need to access their value, but the access method depends on the data...
  • Nicholas (14 days 13 hours ago): In case anyone is looking for more info on the toolbar: I ran into some problems creating a toolbar with the lightweight panel. Previously, the Browser Panel had an addToolbar...
  • Jeroen Boschma (17 days 20 hours ago): I do not seem to get the scrollbars (horizontal…) working in Matlab 2020b. Snippets of init-code (all based on Yair’s snippets on this site) handles.text_explorer...
  • Yair Altman (45 days 22 hours ago): m_map is a mapping tool, not even created by MathWorks and not part of the basic Matlab system. I have no idea why you think that the customizations to the builtin bar function...
  • chengji chen (46 days 5 hours ago): Hi, I have tried the method, but it didn’t work. I plot figure by m_map toolbox, the xticklabel will add to the yticklabel at the left-down corner, so I want to move down...
  • Yair Altman (53 days 22 hours ago): @Alexander – this is correct. Matlab stopped including sqlite4java in R2021b (it was still included in 21a). You can download the open-source sqlite4java project from...
  • Alexander Eder (59 days 17 hours ago): Unfortunately Matlab stopped shipping sqlite4java starting with R2021(b?)
  • K (66 days 4 hours ago): Is there a way to programmatically manage which figure gets placed where? Let’s say I have 5 figures docked, and I split it into 2 x 1, I want to place 3 specific figures on the...
Contact us
Captcha image for Custom Contact Forms plugin. You must type the numbers shown in the image
Undocumented Matlab © 2009 - Yair Altman
This website and Octahedron Ltd. are not affiliated with The MathWorks Inc.; MATLAB® is a registered trademark of The MathWorks Inc.
Scroll to top