Skip to content

fix(input-number): input number 输入 0.00000001 会自动变成科学计数法 - #3600

Open
aaamrh wants to merge 1 commit into
arco-design:mainfrom
aaamrh:fix/input-number-scientific-notation
Open

fix(input-number): input number 输入 0.00000001 会自动变成科学计数法#3600
aaamrh wants to merge 1 commit into
arco-design:mainfrom
aaamrh:fix/input-number-scientific-notation

Conversation

@aaamrh

@aaamrh aaamrh commented Sep 11, 2025

Copy link
Copy Markdown

Types of changes

  • New feature
  • Bug fix
  • Enhancement
  • Component style change
  • Typescript definition change
  • Documentation change
  • Coding style change
  • Refactoring
  • Test cases
  • Continuous integration
  • Breaking change
  • Others

Background and context

input number 组件输入小数会变成科学计数法,0.000000001 -> 1e-8 , 这是机器影响用户体验。
并且 react 版本并不存在这个问题。
经过搜索发现早期 arco-design-vue是修复过这个问题的 arco-design/arco-design#865

问题复现路径:
在文档中就能复现
image

Solution

  • 新增 toSafeString 工具函数来处理科学计数法转换

  • 修改 getStringValue 函数,使用 toSafeString 替代原生的 String() 方法

  • 使用 number-precision 库确保精确的数值转换

  • 📁 packages/web-vue/components/input-number/utils.ts - 新增工具函数

  • 📁 packages/web-vue/components/input-number/input-number.tsx - 修改核心逻辑

  • 📁 packages/web-vue/components/input-number/__test__/index.test.ts - 添加测试用例

How is the change tested?

添加并通过了组件测试用例。

1.234e5 => 123400

-0.000000000000000000001 => -0.000000000000000000001
等,具体文件在 packages/web-vue/components/input-number/test/index.test.ts`

Changelog

Component Changelog(CN) Changelog(EN) Related issues
InputNumber InputNumber 组件始终使用非科学计数法展示数值。 The InputNumber component always displays numbers in non-scientific notation. #3599

Checklist:

  • Test suite passes (npm run test)
  • Provide changelog for relevant changes (e.g. bug fixes and new features) if applicable.
  • Changes are submitted to the appropriate branch (e.g. features should be submitted to feature branch and others
    should be submitted to main branch)

@codesandbox

codesandbox Bot commented Sep 11, 2025

Copy link
Copy Markdown

Review or Edit in CodeSandbox

Open the branch in Web EditorVS CodeInsiders

Open Preview

@censujiang

Copy link
Copy Markdown
Contributor

有人出来merge吗?这个需求我也很需要

@evanshe

evanshe commented Jan 7, 2026

Copy link
Copy Markdown

Preparing review...

2 similar comments
@evanshe

evanshe commented Jan 7, 2026

Copy link
Copy Markdown

Preparing review...

@evanshe

evanshe commented Jan 7, 2026

Copy link
Copy Markdown

Preparing review...

@evanshe

evanshe commented Jan 7, 2026

Copy link
Copy Markdown

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

🎫 Ticket compliance analysis 🔶

3599 - Partially compliant

Compliant requirements:

  • Fix the issue where the InputNumber component displays very small decimal numbers in scientific notation.
  • Ensure the fix handles a range of edge cases, including very large numbers and very small numbers, without using scientific notation.

Non-compliant requirements:

  • Ensure the fix is consistent with the behavior of the React version of the component.

Requires further human verification:

  • Manual verification in the browser/UI to confirm the fix works as expected and matches the React version's behavior.
⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Edge Case Handling

The toSafeString function contains complex string manipulation and regex logic for converting numbers. Review the logic for handling numbers with many decimal places and large integers to ensure it correctly formats all edge cases without introducing rounding errors or performance issues.

export function toSafeString(number: number | string): string {
  // Use native Number.toString when it is NaN or non-scientific notation
  const nativeNumberStr = number.toString();
  if (Number.isNaN(+number) || !nativeNumberStr.includes('e')) {
    return nativeNumberStr;
  }

  try {
    const isNegative = number < 0;
    const absoluteValue = Math.abs(+number);
    // Get decimal length
    const digitLength = NP.digitLength(absoluteValue);
    // Convert decimal to integer
    const integerNum = NP.float2Fixed(absoluteValue);
    // Convert integer to non-scientific notation string
    const integerStr = integerNum
      .toString()
      .replace(/e\+(\d+)/i, (_, $1) => new Array(+$1).fill(0).join(''));

    return `${isNegative ? '-' : ''}${
      digitLength === 0
        ? integerStr
        : integerStr.replace(new RegExp(`\\d{1,${digitLength}}$`), (match) => {
            const decimalStr = `${new Array(digitLength)
              .fill(0)
              .join('')}${match}`.slice(-digitLength);
            return `${integerStr.length <= digitLength ? 0 : ''}.${decimalStr}`;
          })
    }`;
  } catch (e) {
    // If any error occurs, fallback to native string conversion
  }

  return nativeNumberStr;
}
Fallback Behavior

The getStringValue function now uses toSafeString for numbers without a precision set. Validate that the fallback to the native string conversion in toSafeString (when an error occurs) is robust and does not cause unexpected display issues.

  const numString = mergedPrecision.value
    ? number.toFixed(mergedPrecision.value)
    : toSafeString(number);
  return props.formatter?.(numString) ?? numString;
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants