Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
A very powerful and easy-to-use number precision calculation and formatting library.
:baby_chick:Easy Push the coding experience to the extreme, the minimalist API is easy to remember.
:rocket:Fast Continuously optimizing details, it now operates very quickly.
💪Powerful Precise number calculation, number formatting, complete rounding rules, unit calculation, robust type hinting.
:snake:Flexible The flexible API allows you to write freely, however you want.
:corn:Practical Born from actual business, it covers all practical operations in the business.
Supported operators : + - * / % ** //
Document language: English | 简体中文
npm install a-calc
commonjs
const {calc, fmt} = require("a-calc")
// or
const {calc, fmt} = require("a-calc/cjs")
es module
import {calc, fmt} from "a-calc"
// or
const {calc, fmt} from "a-calc/es"
Browser side
<script src="https://unpkg.com/a-calc@latest/browser/index.js"></script> <!-- cdn -->
<script src="node_modules/a-calc/browser/index.js"></script> <!-- After installing npm, you can also import it locally. Choose either option. -->
<script>
const {calc, fmt} = a_calc
</script>
calc("0.1 + 0.2") // "0.3"
// A more complex calculation
calc("0.1 + 0.2 * 0.3 / 0.4 * (0.5 + 0.6)") // "0.265"
// Scientific notation calculation
calc("-2e2 + 3e+2") // "100"
// Calculations with units
calc("0.1% + 0.2%", {_unit: true}) // "0.3%"
// Variable operation
calc("(a * (b + c))", {a: 1, b: 2, c: 3}) // "5"
calc("(a * (b + c))", [{a: 1, b: 2}, {c: 3}]) // "5"
calc("a + b", {a: "2$", b: "4$", _unit: true}) // "6$"
calc("a + b", {_fill_data: [{a: "2$"}, {b: "4$"}], _unit: true}) // "6$"
// Calculate and format: Thousands separator
calc("a + b | ,", {a:324232421123, b: 234234242422321}) // "234,558,474,843,444"
// Calculate and format: fractions
calc("2 * 3 | /") // "6/1"
// Calculate and format: output numbers.
calc("1 + 1 | !n") // 2
By default, spaces in expressions are not required, unless you use the space or space-all mode or the calc_lite function, which are introduced in later chapters. However, I recommend that you always include spaces in expressions, which look clearer and nicer.
let a = 0.000001
let b = 888.789
calc("a + b", {a,b}) // "888.789001"
calc("a * (b + c) % d + 7.123", [
{a: 1, b: 2},
{c: 3, d: 4}
]) // "8.123"
// A bit more complex
calc("1 + o.a / arr[0].d",{
o: { a: 2 },
arr: [{ d: 8 }]
}) // "1.25"
calc("a + b - c",[
{a: 1},
{b: 2, c: 3}
]) // "0"
The actual situation is not always ideal, maybe we have to calculate two percentage numbers. Fortunately, a-calc now supports these operations, but please note that the unit will be taken from the first number carrying a unit, and the units later will be ignored.
// Please note that _unit is required and not enabled by default. This is because calculations with units will perform some additional operations, and in contrast, pure numerical calculations are faster.
calc("1 + 2%", {_unit: true}) // "3%"
calc("1.123$$$ + 2.88% | + =6", {_unit: true}) // "+4.003000$$$"
// Starting from a-calc@2.0.0, the array form of filling data can also be configured. You can use the configuration object as the first or the last parameter of the array. These are the only two positions that are supported.
calc("a + b", [{a: "1%", b: "2%"}, {_unit: true}]) // "3%"
In actual development, you may hope that the final result does not automatically carry units. In versions after 1.3.6, you can remove units from the result through the formatting parameter !u
, or you can directly output the number with !n
.
Formatting supports the following functions: limiting the number of decimal places, preserving positive and negative signs, outputting as a percentage, outputting in scientific notation, outputting, and they can be combined. However, there are some situations where combinations do not work. You can try it yourself, there are too many combination situations, and I won't list them all.
Formatting list:
>or>=or<or<=or=number
means to limit the number of decimal places, for example: <=2
means the number of decimal places should be less than or equal to 2 >3
means the number of decimal places must be greater than 3, this is equivalent to >=4
,
Output as a thousandth place numeric string/
Output as a fraction+
The output positive numbers are marked with a +
sign%
Output percentage numbers, which can be combined with the option to limit the number of decimals.!e
Output in scientific notation, e can be capitalized!n
Output as a number, not a numeric string, n can be capitalized. After version 1.3.6, this has the highest priority, and any other formatting parameters cannot affect this parameter.!u
Remove units from the result// Operate the decimal places
calc("0.1 + 0.2 | =2") // "0.30"
calc("0.11111 + 0.11111 | <=4") // "0.2222"
calc("0.11 + 0.11 | <=4") // "0.22"
calc("0.1 + 0.2 | >= 5") // "0.30000"
calc("0.0000001+ 0.0000001 | >= 5") // "0.0000002"
// Preserve positive and negative signs
calc("1 + 1 | +") // "+2"
// Thousandth place
calc("10000000 + 100000000 | ,") // "110,000,000"
// Fraction
calc("0.025 + 0.2 | /") // "9/40"
// Percentage
calc("1 + 1 | %") // "200%"
// Scientific notation, note that this e can also be capitalized
calc("1 + 1 | !e") // "2e+0"
// Simultaneously specify decimals and thousandth place while preserving the positive and negative signs
calc("10000000 + 100000000 | +,=10") // "+110,000,000.0000000000"
The rounding rules are added to the part of the formatting string, and their symbols are:
~-
Truncation, the default rounding rule~+
Increment~5
Rounding~6
Round to Even, this rounding rule is more accurate than the normal rounding. The rule is different when the number after the rounding is 5. It will check the position after 5. If the number after 5 is not 0, it will increment. If the number after 5 is 0, it will check whether the number before 5 is even or not. If it is even, it will not increment. If it is not even, it will increment.calc("0.11 + 0.22 | =1 ~+") // "0.4" Keep one place and increment it
calc("0.55 | =1 ~5") // "0.6"
calc("0.65 | =1 ~6") // "0.6"
This newly added rounding rule seems to make the formatting part longer, but the actual situation is not like this. Generally, the rounding rule of a project is fixed, so the formatting part of the rounding rule should be encapsulated in the default formatting parameters. When it is actually used, there is no need to write this part of the content at all. Refer to the following default formatting
instructions.
calc("0.1 | =2") // "0.10"
fmt("0.1 | =2") // "0.10"
// calc has the function of fmt, but fmt has better semantics
fmt("1000000 | ,") // "1,000,000"
You can turn on or off the console printing of the current library version number, and you can also turn on or off console prompts for whether there is a new version update.
import { calc_util } from "a-calc"
calc_util.print_version(); // Print the version in the console
calc_util.check_update(); // Enable the update detection function. If there are updates, it will remind you in the console.
Error handling
Typically, using calc directly requires that the input calculation formula is completely correct, and by default a-calc will not help you handle errors in the formula. This can be filtered out by oneself, but in the project, we might not want to do this, so we need an additional advanced API to silently capture and give an appropriate return value when the input formula is incorrect.
calc("1 + 2sd + d",{
_fill_data: {d: 3}, // From here, the data source object needs to be assigned to _fill_data. This object can also be an array of objects. At this time, when obtaining data, it is searched item by item from the array, and it stops immediately when the first one is found.
_error: "-", // When the calculation formula is wrong, it returns - as an alternative value.
})
// The above writing can be simplified a bit.
calc("1 + 2sd + d", {
d: 8,
_error: "-"
}) // This simplification is purely for convenience.
Default formatting
In actual projects, you can optimize the development experience through default formatting.
calc("111111 + 11111 | ,",{_fmt: "=2"}) // "122,222.00" Obviously , and =2 are combined, and the format string in the expression has a higher priority.
In actual projects, the core calc function may not be extremely convenient. Therefore, a-calc
provides a built-in function calc_wrap
for secondary encapsulation after version 1.2.10. Essentially, it is an extension of calc, so it has all the former's capabilities but with more flexible writing methods and powerful type inference.
Please note that this may not be the only correct way to encapsulate. I just provided this feature. There is no dogma here. You should adapt flexibly to your own scenarios.
I suggest that if you decide to bring calc_wrap into the project, you can rename it as calc to save a few characters. The following will show some flexible writing methods and powerful type inference.
// Note that here we rename calc_wrap as calc, because if you need to use the calc_wrap function, the core calc function is basically not needed, so if this good name is idle, it should be used.
import { calc_wrap as calc } from "a-calc";
const state = {
a: 1,
b: 2,
c: 3
};
// When the passed parameter is a calculation formula without a variable name, it will directly return the calculation result.
calc( "(1 + 2) * 3" ); // Return type: string
// When the passed parameter is a suspected calculation formula containing a variable name and there is no second data source parameter, a function waiting for a data source to be passed will be returned. Yes, this function is achieved through static type deduction.
calc( "(a + b) * c" ); // Return type: ( data: any ) => string
calc( "(a + b) * c" )( state ); // Return type: string
// Maybe you want to inject the state first and then enter the expression. This is also possible.
calc( state ); // Return type: ( expr: string | number ) => string
calc( state )( "(a + b) * c" ); // Return type: string
// The original usage is naturally also supported.
calc( "a + b + c", state ); // Return type: string
// You can still mix configuration and data sources together, which is very convenient.
calc( "a + b + c" )( { ...state, _error: 0 } ); // Return type: string | 0
a-calc
can use the template string syntax, but I found that the readability of this writing method is very poor in practice. Unless you really have a sufficiently reasonable reason, it is not recommended to use the template string syntax.
calc(`${a} + ${b}`) // This way of writing is not recommended.
calc("a + b", {a,b}) // Recommended writing, because it is clearer.
The two modes of space and space-ALL put forward higher requirements for code writing. space mode requires strict insertion of Spaces between each unit of the calculation part. Space-all not only requires strict insertion of Spaces in the calculation part but also requires insertion of Spaces in the fmt formatting part. Almost the most important effect of this feature is disambiguation, and the second is that it can improve performance slightly.
calc("1+1", {_mode: "space"}) // This formulation cannot be calculated because of the lack of Spaces
calc("1 + 1", {_mode: "space"}) // This is written correctly
calc("1 + (2 * 3)", {_mode: "space"}) // This is also correct, because of the special treatment of parentheses, which can be next to internal numbers or variable names or separated by Spaces
calc("1 + ( 2 * 3 ) | =2 ,", {_mode: "space-all"}) // space is also required between =2 and, after using the space-all mode, there must be at least one space between each formatting unit, and the space can be more than less.
You can also use plus sub mul div and other methods to calculate, although the main problem that a-calc solves is that such methods are not intuitive to write the problem, but if you only have two operands and do not need any formatting then using these methods can bring some performance improvement
import {plus, sub, mul, div, mod, pow, idiv} from "a-calc"
plus(1, 1) // 2
plus(1, 1, "string") // "2"
calc_lite
is a streamlined version of calc. Its functions are not as comprehensive as calc, but its internal logic is simpler and its performance is stronger than calc (but the gains are limited). Similarly, there are also some drawbacks. The writing experience is not as good as calc, and it is not as powerful as calc. Some functions are not available in calclite: the function does not support unit operations, does not support mode specification, and does not support calculations like - ( 3 - - ( -2 ) )
.
The arithmetic and formatting parts of the calc_lite
function are passed in separately, and all internal units of the calculation must be strictly separated by spaces! This function does not exist to replace calc
, it is just a streamlined version of calc's logic, sacrificing some infrequently used functionality and writing experience for a limited performance improvement.
Note that this function will not throw any exceptions. By default, when an error occurs, the function will return -
.
import {calc_lite} from "a-calc"
// The function has a total of 4 parameters, namely calcexpr, fmtexpr, data, err_value = "-", they correspond to the calculation, formatting string, filling data, and return value when an error occurs.
// Only the first parameter must be passed in, the others can be omitted. If you want to skip passing in, you can pass in null or undefined.
calc_lite("a + b", null, {a: 0.1, b: 0.2}) // "0.3"
calc_lite("1 + 2 + b") // "-"
calc_lite("1", "=2") // "1.00"
calc_lite("( 1 + 2 ) * 3") // "9" Spaces must be strictly inserted on both sides of the parentheses.
calc_lite("1+1") // "-" The calculation error is caused by the fact that the units in the calculation are not strictly separated by spaces.
2.2.7
calc_lite
function has made its usage more flexible now.2.2.0
calc_lite
function.2.1.0
2.0.0
plus(1, 1)
//
floor division operator.**
to right-bound to be consistent with the native JS language rules1.3.9 Solved the problem of failed rounding due to the part of the injection variable in formatting being 0 (Problem reporter: MangMax)
1.3.8 Solved the packaging failure problem caused by the upgrade of vite5.x (Problem reporter: 武建鹏)
1.3.6
!n
formatting parameter has been adjusted to the highest, and no other formatting parameters can affect it.!u
formatting parameter, which can remove the unit part from the result.1.3.4
1.3.0
1.2.30
1.2.10
calc_wrap
, which is a secondary wrapper for the core function calc
and can be used directly.1.2.6
1.2.0
-e
and -n
have been changed to !e
and !n
, respectively.1.1.0
\e
scientific counting output is now -e
, others did not change-n
to output the number type<
and >
symbols.1.0.25
1.0.23
1.0.22
1.0.21
1.0.19
1.0.14
**
operator precedence error.<=
.1.0.12
1.0.10
1.0.6
_fillData
is now _fill_data
, as snake_case naming is clearer.\e
, which can format numbers in scientific notation.0.0.80
0.0.79
0.0.78
0.0.72
calc("1yuan", {_unit: true})
or fmt("1yuan | =2",{_unit: true})
To be determined
When providing feedback, please include error examples and as much information about the issue as possible. Avoid submitting overly abstract or general statements as feedback! A new version addressing the problem will typically be released within one working day.
FAQs
A very powerful and easy-to-use number precision calculation and formatting library.
The npm package a-calc receives a total of 18,546 weekly downloads. As such, a-calc popularity was classified as popular.
We found that a-calc demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.