在 C# 中格式化带有有效数字的数字

2023-12-10

我有一些十进制数据,正在将其推送到要查看的 SharePoint 列表中。我想根据我对具体计算的了解来限制结果数据中显示的有效数字的数量。有时它会是3,所以12345会变成12300,0.012345会变成0.0123。偶尔会是 4 或 5。有什么方便的方法来处理这个吗?


See: 舍入到有效数字由“P爸爸”。
我把他的方法与我喜欢的另一种方法结合起来。

在 TSQL 中舍入到有效数字要容易得多,其中舍入方法基于舍入位置,而不是小数位数 - .Net math.round 就是这种情况。您可以将 TSQL 中的数字四舍五入到负数,这将四舍五入为整数 - 因此不需要缩放。

另请参阅此其他线程。 Pyrolistical的方法很好。

对我来说,问题的尾随零部分似乎更像是字符串操作,因此我包含了一个 ToString() 扩展方法,该方法将在必要时填充零。

using System;
using System.Globalization;

public static class Precision
{
    // 2^-24
    public const float FLOAT_EPSILON = 0.0000000596046448f;

    // 2^-53
    public const double DOUBLE_EPSILON = 0.00000000000000011102230246251565d;

    public static bool AlmostEquals(this double a, double b, double epsilon = DOUBLE_EPSILON)
    {
        // ReSharper disable CompareOfFloatsByEqualityOperator
        if (a == b)
        {
            return true;
        }
        // ReSharper restore CompareOfFloatsByEqualityOperator

        return (System.Math.Abs(a - b) < epsilon);
    }

    public static bool AlmostEquals(this float a, float b, float epsilon = FLOAT_EPSILON)
    {
        // ReSharper disable CompareOfFloatsByEqualityOperator
        if (a == b)
        {
            return true;
        }
        // ReSharper restore CompareOfFloatsByEqualityOperator

        return (System.Math.Abs(a - b) < epsilon);
    }
}

public static class SignificantDigits
{
    public static double Round(this double value, int significantDigits)
    {
        int unneededRoundingPosition;
        return RoundSignificantDigits(value, significantDigits, out unneededRoundingPosition);
    }

    public static string ToString(this double value, int significantDigits)
    {
        // this method will round and then append zeros if needed.
        // i.e. if you round .002 to two significant figures, the resulting number should be .0020.

        var currentInfo = CultureInfo.CurrentCulture.NumberFormat;

        if (double.IsNaN(value))
        {
            return currentInfo.NaNSymbol;
        }

        if (double.IsPositiveInfinity(value))
        {
            return currentInfo.PositiveInfinitySymbol;
        }

        if (double.IsNegativeInfinity(value))
        {
            return currentInfo.NegativeInfinitySymbol;
        }

        int roundingPosition;
        var roundedValue = RoundSignificantDigits(value, significantDigits, out roundingPosition);

        // when rounding causes a cascading round affecting digits of greater significance, 
        // need to re-round to get a correct rounding position afterwards
        // this fixes a bug where rounding 9.96 to 2 figures yeilds 10.0 instead of 10
        RoundSignificantDigits(roundedValue, significantDigits, out roundingPosition);

        if (Math.Abs(roundingPosition) > 9)
        {
            // use exponential notation format
            // ReSharper disable FormatStringProblem
            return string.Format(currentInfo, "{0:E" + (significantDigits - 1) + "}", roundedValue);
            // ReSharper restore FormatStringProblem
        }

        // string.format is only needed with decimal numbers (whole numbers won't need to be padded with zeros to the right.)
        // ReSharper disable FormatStringProblem
        return roundingPosition > 0 ? string.Format(currentInfo, "{0:F" + roundingPosition + "}", roundedValue) : roundedValue.ToString(currentInfo);
        // ReSharper restore FormatStringProblem
    }

    private static double RoundSignificantDigits(double value, int significantDigits, out int roundingPosition)
    {
        // this method will return a rounded double value at a number of signifigant figures.
        // the sigFigures parameter must be between 0 and 15, exclusive.

        roundingPosition = 0;

        if (value.AlmostEquals(0d))
        {
            roundingPosition = significantDigits - 1;
            return 0d;
        }

        if (double.IsNaN(value))
        {
            return double.NaN;
        }

        if (double.IsPositiveInfinity(value))
        {
            return double.PositiveInfinity;
        }

        if (double.IsNegativeInfinity(value))
        {
            return double.NegativeInfinity;
        }

        if (significantDigits < 1 || significantDigits > 15)
        {
            throw new ArgumentOutOfRangeException("significantDigits", value, "The significantDigits argument must be between 1 and 15.");
        }

        // The resulting rounding position will be negative for rounding at whole numbers, and positive for decimal places.
        roundingPosition = significantDigits - 1 - (int)(Math.Floor(Math.Log10(Math.Abs(value))));

        // try to use a rounding position directly, if no scale is needed.
        // this is because the scale mutliplication after the rounding can introduce error, although 
        // this only happens when you're dealing with really tiny numbers, i.e 9.9e-14.
        if (roundingPosition > 0 && roundingPosition < 16)
        {
            return Math.Round(value, roundingPosition, MidpointRounding.AwayFromZero);
        }

        // Shouldn't get here unless we need to scale it.
        // Set the scaling value, for rounding whole numbers or decimals past 15 places
        var scale = Math.Pow(10, Math.Ceiling(Math.Log10(Math.Abs(value))));

        return Math.Round(value / scale, significantDigits, MidpointRounding.AwayFromZero) * scale;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 C# 中格式化带有有效数字的数字 的相关文章

随机推荐

  • 在Powershell中使用升级后的FolderBrowserDialog(“Vista风格”)

    我在用着电源外壳使用户能够浏览 Node js 应用程序的文件 文件夹路径 因为到目前为止我还没有找到更好的轻量级替代方案 并且我遇到了处理可怕的 可怜的问题的老问题可用性FolderBrowserDialog不支持 粘贴路径 访问快速访问
  • 在发布模式下构建解决方案时,“LinkAssemblies”任务意外失败

    我的项目正在成功构建Debug模式 但是当我将其更改为Release模式 出现以下异常 Severity Code Description Project File Line Suppression State Error The Link
  • 停止执行 Groovy 脚本

    我正在我的代码中嵌入 Groovy 运行时 并且我希望能够中断它 我无法控制将要运行的脚本 我读到有关 groovy transform ThreadInterrupt 来处理线程中断的信息 但由于某种原因 下面的代码无法按预期工作 它实际
  • String.intern() 的垃圾收集行为

    如果我使用 String intern 来提高性能 因为我可以使用 来比较实习字符串 我会遇到垃圾收集问题吗 内部字符串的垃圾收集机制与普通字符串有何不同 String intern 管理一个内部的 本机实现的池 它具有一些与 GC 相关的
  • 如何水平居中DIV

    如何将 DIV 与此 URL 上的文本框和按钮水平居中 http tinyurl com d4lpyh5 问候 凯文 在第 10 行 您应该为 div 添加宽度 改变 div style margin left auto margin ri
  • dojo dgrid 中不区分大小写的排序

    是否可以不区分大小写进行排序 例如 默认情况下排序显示如下 Awesomeman adam beyonce 但是 我想排序 adam Awesomeman beyonce 是否可以轻松地覆盖灵敏度 据我所知 网格继承自OnDemandGri
  • std::mersenne_twister_engine 和随机数生成

    如果我执行以下操作 会生成什么分布 均匀分布 泊松分布 正态分布等 输出似乎表明均匀分布 但是 为什么我们需要std uniform int distribution int main std mt19937 64 generator 13
  • org.json.JSONException:在 android 的字符 0 处输入结束

    我正在实现一个 Android 应用程序并尝试制作注册和登录屏幕 我的应用程序已连接到服务器 这是我的代码出错的部分 public void onResponse String response Log d TAG Register Res
  • 在 SQL 中进行复制时,我可以将旧密钥链接到新密钥吗?

    我正在尝试复制表中的记录并使用 SQL Server 2005 中的存储过程更改一些值 这很简单 但我还需要使用新的主键复制其他表中的关系 由于此过程用于批量复制记录 我发现很难存储旧密钥和新密钥之间的某些关系 现在 我正在使用 OUTPU
  • 当我使用 SupportStreetViewPanoramaFragment 时应用程序崩溃

    我想在 StrretView 中开始一些开发 为此我使用了 SupportStreetViewPanoramaFragment 但是当我启动我的应用程序时 它崩溃并显示以下 logcat 07 17 16 33 53 805 E Andro
  • 本地通知“每天上午 7:00”未通知

    我希望每天 7 00 发出通知 但它不会发出 我还希望它在锁定屏幕中显示 这是迄今为止我拥有的所有代码 void EveryDayNotify NSLog Good Morning Working UILocalNotification l
  • 如何在不使用 AudioSessionSetProperty 的情况下将音频路由到扬声器?

    As AudioSessionSetProperty可能会变成deprecated 我正在尝试找到如何将音频路由到的代码示例speaker使用其他方式 之前我做了以下事情 void setSpeakerEnabled debugLog s
  • 为什么“加载事件在 addEventListener() 上不起作用”?

    我尝试在加载页面的正文元素后记录一些内容 但日志没有出现在控制台中 我究竟做错了什么 const body document querySelector body function setInitialGradient console lo
  • 按相关列值排序 Bookshelf.js 获取

    我正在使用 Bookshelf js Knex js 获取具有相关子模型 称为公司 的模型 称为用户 我可以按子模型上的字段订购吗 company name 另外 如果可能的话 我可以进行多重排序吗 company name然后下降last
  • 使用 Google Apps 脚本编辑 Google 日历活动时更新与会者

    情况 我有一个日历 上面有很多活动 员工评估 我已经做了很多修改 改变活动的长度等 但邀请函是发给拥有莲花笔记日历的人 穷人 的 这意味着除非我触发所谓的 发送通知 在用鼠标点击的版本中 他们无法知道事件已更新 类似问题 在此示例中 我尝试
  • 如何截取画布的屏幕截图? [复制]

    这个问题在这里已经有答案了 如何截取画布的屏幕截图 或者如何创建图像 该图像将由图像 自由区域组成 位于画布上 这取决于你的框架 但基本上你可以使用canvas toDataURL 这是一个完整的例子
  • 如何使用 python 运行 matplotlib 和 PyQt5 Video

    我正在尝试一起运行 QVideoWidget 和 matplotlib 动画 但是当我运行这个 py 时 QVideoWidget 不起作用 我得到了 QVideoWidget 代码和 matplotlib 动画代码 然后将这些代码总结在下
  • 如何在带有后续提示的 QnA 问题中实现卡片并在卡片中使用它们

    我已经设置了一个链接到 QnA 服务的简单 QnA 机器人 在 QnA 服务中 我设置了一些带有后续提示的问题 家属 例如我如何乘坐公共汽车 火车等到达校园 请参阅链接中的图像 在 Qna 制造商测试功能中 您只需单击一个名为 启用多轮 的
  • 当我们将命令放在美元符号和括号内时,在 shell 中意味着什么:$(command)

    我只想了解 shell 中的以下代码行 它用于获取当前工作目录 我知道 variable name 返回变量名称内的值 但是什么是 command 应该回来吗 执行命令后是否返回值 在这种情况下 我们可以使用 执行命令 CWD cd dir
  • 在 C# 中格式化带有有效数字的数字

    我有一些十进制数据 正在将其推送到要查看的 SharePoint 列表中 我想根据我对具体计算的了解来限制结果数据中显示的有效数字的数量 有时它会是3 所以12345会变成12300 0 012345会变成0 0123 偶尔会是 4 或 5