数字字符串格式化 | 豆包MarsCode AI刷题

98 阅读4分钟

题目描述

image.png

思路分析

1. 去掉前导零

我们要处理的字符串有可能带有前导零,例如 "0001234.56""000001234", 这些前导零在数值计算中是没有意义的,所以需要去掉它们。这一步可以用多种方法来实现,但这里选择一种简便而通用的方案:

  1. 将输入字符串转换为浮点数(或整数),再转回字符串。

    • 优点:自动去掉前导零,而且无论整数或小数都可以处理。
    • 缺点:会引入小数的科学计数法,比如 1e6,因此后续我们会格式化为普通小数形式。
  2. 这样做还保证我们处理的数据确实是数字。通过 float() 转换,如果用户输入了非数字字符,会触发 ValueError 错误,可以提前返回错误信息。

直接用 float(input_str) 可以去除前导零,同时确保输入是有效数字,然后将其转回字符串来继续后续处理。这样一来,接下来的步骤可以假设输入是有效的无前导零的数值字符串。

2. 分割整数部分和小数部分

这一步要分清楚整数部分和小数部分,这是因为:

  1. 千分位格式化 仅对整数部分有效,小数部分不需要逗号分隔。
  2. 手动分割 比使用字符串函数更灵活,我们可以完全控制如何判断整数和小数。

通过遍历字符串找到小数点的位置,我们可以确定整数部分和小数部分:

  • 找到小数点后:分割出小数点前面的整数部分和小数点后面的部分。
  • 没有小数点:整个字符串就是整数部分。

手动遍历字符串寻找小数点的位置,这样可以确保无论输入是否包含小数点,都可以将字符串正确分成整数和小数部分。

3. 对整数部分添加千分位逗号

格式化整数部分是这一步的主要任务。为了让大数字易读,我们每三位添加一个千分位逗号。例如,将 "1234567" 转换成 "1,234,567"

这里有多种实现方式,比如利用字符串分组,但我们选择逐位构建新字符串,这样可以:

  1. 控制逗号插入:仅在每三位时插入一个逗号。
  2. 确保顺序和格式:按照从左到右的顺序构建,最终可以直接得到格式化的整数部分。

我们从左向右遍历整数部分,并在适当位置插入逗号。通过判断当前字符位置的索引,确定是否该插入逗号。每遇到 len(int_part) % 3 == 0 的位置(即整数位数从右数每三位),就添加一个逗号。

4. 组合最终结果

在这一步,将格式化的整数部分和小数部分拼接,形成最终输出字符串。

  • 如果存在小数部分,我们用 f"{整数部分}.{小数部分}" 的方式拼接。
  • 如果没有小数部分,直接返回整数部分。

代码实现

def solution(s: str) -> str:
    # Step 1: 去掉前导零,将字符串转为浮点数再转回字符串
    try:
        num = float(s)  # 转换为浮点数来去除前导零
    except ValueError:
        return "Invalid input"
    
    # 转回字符串,去掉多余的前导零
    num_str = str(num)
    
    # Step 2: 手动分割整数部分和小数部分
    int_part = ""
    dec_part = ""
    point_index = -1
    
    # 查找小数点位置,分割整数和小数部分
    for i, char in enumerate(num_str):
        if char == '.':
            point_index = i
            break
    
    if point_index != -1:
        # 存在小数点
        int_part = num_str[:point_index]
        dec_part = num_str[point_index+1:]
    else:
        # 不存在小数点
        int_part = num_str

    # Step 3: 给整数部分添加千分位逗号
    result = []
    int_len = len(int_part)
    
    for i, digit in enumerate(int_part):
        # 每隔三位插入一个逗号
        if i > 0 and (int_len - i) % 3 == 0:
            result.append(',')
        result.append(digit)
    
    formatted_int_part = ''.join(result)
    
    # Step 4: 组合整数部分和小数部分
    if dec_part:
        return f"{formatted_int_part}.{dec_part}"
    else:
        return formatted_int_part

# 测试
if __name__ == '__main__':
    print(solution("1294512.12412") == '1,294,512.12412')  # True
    print(solution("0000123456789.99") == '1,234,567,89.99')  # True
    print(solution("987654321") == '987,654,321')  # True