Giter Site home page Giter Site logo

format_num's Introduction

format_num

Dynamic formatting of numbers into human readable forms.

Did you encounter cases where Rust doesn't represent numbers the way you expect?

for i in 1..=10 {
    println!("{}", 0.1 * i as f64);
}

You get this:

0.1
0.2
0.30000000000000004
0.4
0.5
0.6000000000000001
0.7000000000000001
0.8
0.9
1

That's actually not a Rust issue, but rather how floats are represented in binary.

Yet rounding error is not the only reason to customize number formatting. A table of numbers should be formatted consistently for comparison; above, 1.0 would be better than 1. Large numbers may need to have grouped digits (e.g. 42,000) or be in scientific or metric notation (4.2e+4, 42k). Reported numerical results should be rounded to significant digits (4021 becomes 4000) and so on.

The parser is modeled after Python 3's format specification mini-language (PEP3101) with some minor implementation details changes.

The general form of a format specifier is:

[[fill]align][sign][symbol][0][width][,][.precision][type]

The fill can be any character. The presence of a fill character is signaled by the align character following it, which must be one of the following:

> - Forces the field to be right-aligned within the available space.

< - Forces the field to be left-aligned within the available space.

^ - Forces the field to be centered within the available space.

= - like >, but with any sign and symbol to the left of any padding.

The sign can be:

- - nothing for zero or positive and a minus sign for negative (default behavior).

+ - a plus sign for zero or positive and a minus sign for negative.

(space) - a space for zero or positive and a minus sign for negative.

The symbol can be:

The # option causes the “alternate form” to be used for the conversion. The alternate form is defined differently for different types. For integers, when binary (b), octal (o or O), or hexadecimal (x or X) output is used, this option adds the prefix respective "0b", "0o", "0O" or "0x" to the output value. For floats, the alternate form causes the result of the conversion to always contain a decimal-point character, even if no digits follow it.

The zero (0) option enables zero-padding; this implicitly sets fill to 0 and align to =.

The width defines the minimum field width; if not specified, then the width will be determined by the content.

The comma (,) option enables the use of a group separator, such as a comma for thousands.

Depending on the type, the precision either indicates the number of digits that follow the decimal point (types f and %), or the number of significant digits (types e and s). If the precision is not specified, it defaults to 6 for all types. Precision is ignored for integer formats (types b, o, d, x and X).

The available type values are:

e - exponent notation.

f - fixed point notation.

s - decimal notation with an SI prefix, rounded to significant digits.

% - multiply by 100, and then decimal notation with a percent sign.

b - binary notation, rounded to integer.

o - octal notation, rounded to integer.

d - decimal notation, rounded to integer.

x - hexadecimal notation, using lower-case letters, rounded to integer.

X - hexadecimal notation, using upper-case letters, rounded to integer.

Examples

use format_num::{NumberFormat, format_num};

fn main() {
    let num = NumberFormat::new();
    let format_spec = "+14d";
    assert_eq!(num.format(".1f", 0.06), "0.1");
    assert_eq!(num.format("#.0f", 10.1), "10."); // float alternate form (always show a decimal point)
    assert_eq!(num.format("#b", 3), "0b11");
    assert_eq!(num.format("b", 3), "11");
    assert_eq!(num.format(format_spec, 2_147_483_647), "   +2147483647");
    
    // Or, you can use a macro for simplicity
    assert_eq!(format_num!("#X", 48879), "0xBEEF");
    assert_eq!(format_num!(".2s", 42e6), "42M");
    assert_eq!(format_num!(".^20d", 12), ".........12........."); // dot filled and centered
    assert_eq!(format_num!("+10.0f", 255), "      +255");
    assert_eq!(format_num!(".0%", 0.123), "12%");
    assert_eq!(format_num!("+016,.2s", 42e12), "+000,000,000,042T"); // grouped zero-padded with a mandatory sign, SI-prefixed with 2 significant digits
}

Note

A current limitation is that the number to be formatted should implement the Into<f64> trait. While this covers a broad range of use cases, for big numbers (>u64::MAX) some precision will be lost.

Roadmap

Implementation of more types: g (general format), n (number), c (character).

Also, there are plans to add support for locales and currency formatting.

License

format_num is licensed under either of the Apache License, Version 2.0, or the MIT license at your discretion.

format_num's People

Contributors

askanium avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

hiddenmemory

format_num's Issues

Memory allocation issue

When I try the snipped

`let num = format_num::NumberFormat::new();

num.format("s", -0.000000000000000000000000000000000000021414574468187103);`

it produces the output

memory allocation of 83751862272 bytes failed error: process didn't exit successfully: 'target\debug\five_b.exe' (exit code: 0xc0000409, STATUS_STACK_BUFFER_OVERRUN)

Is This Project Still Alive?

There hasn't been any activity in a while. Thank you very much for what you have contributed so far! You are a very talented developer, and I greatly appreciate your contribution with this project!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.