# createRound

> "A surplus of effort could overcome a deficit of confidence." —Sonia Sotomayor

本文为 《lodash 源码阅读》 系列文章，后续内容会在 [github](https://github.com/gu-xionghong/lodash-analysis) 中发布，欢迎 star，[gitbook](https://gu-xionghong.gitbook.io/lodash-analysis/) 同步更新。

## 源码

```javascript
/**
 * 创建一个像 round 类似函数。
 *
 * @private
 * @param {string} methodName 使用 Math中对应的 rounding 方法 ceil/floor/round。
 * @returns {Function} 返回新的 round 函数。
 */
function createRound(methodName) {
  const func = Math[methodName];
  return (number, precision) => {
    precision = precision == null ? 0 : precision >= 0 ? Math.min(precision, 292) : Math.max(precision, -292);
    if (precision) {
      // 使用科学计数法移位以避免浮点问题。
      // 查看 [MDN](https://mdn.io/round#Examples) 获取更多详情。
      let pair = `${number}e`.split('e');
      const value = func(`${pair[0]}e${+pair[1] + precision}`);

      pair = `${value}e`.split('e');
      return +`${pair[0]}e${+pair[1] - precision}`;
    }
    return func(number);
  };
}
```

## 原理

`createRound` 是一个高阶函数，它先将数值转化为 `科学计数法` 表示的字符串，再通过 `移位` 形式，对数值进行 `ceil/floor/round` 操作，最后恢复对应 位值 返回。

### 极限精度值 1e292/1e-292 (TODO)

关于精度 `292/-292` 问题，作者研究了一天也没有理清楚，相关 [issue](https://github.com/lodash/lodash/issues/4232)

### 科学计数法移位计算

`科学计数法移位` 计算的方式可以避免浮点数精度问题，方法逻辑可以剖析成下面流程：

```javascript
// _.ceil(6.004, 2)
const precision = 2;
const number = 6.004;

// 科学计数法
const pair = 0; // 对应指数
const expNumber = '6.004e0';

// 移位 2 个精度
const shiftedExpNumber = `6.004e${0 + precision}`; // 6.004e2
const shiftedNumber = 600.4;

// 进行 ceil 转换
const ceiledShiftedNumber = Math.ceil(shiftedNumber); // 601

// 恢复对应位数
const ceiledNumber = +`${ceiledShiftedNumber}e{0 - precision}`; // +'601e-2' -> 6.01
```

## 相关链接

* [lodash 技巧 —— 高阶函数](https://gu-xionghong.gitbook.io/lodash-analysis/tips/higherorderfunction)
* [lodash 源码阅读 —— ceil](https://gu-xionghong.gitbook.io/lodash-analysis/math/ceil)
* [lodash 源码阅读 —— floor](https://gu-xionghong.gitbook.io/lodash-analysis/math/floor)
* [lodash 源码阅读 —— round](https://gu-xionghong.gitbook.io/lodash-analysis/math/round)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gu-xionghong.gitbook.io/lodash-analysis/.internal/createround.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
