【问题标题】:Is there an C# equivalent of c++ fesetround() function?是否有与 c++ fesetround() 函数等效的 C#?
【发布时间】:2014-08-06 03:38:07
【问题描述】:

我正在编写一个用于区间算术的 C# 库,为此我需要 将浮点运算舍入模式设置为向上和向下。我知道在 C++ 中 它可以通过 fesetround() 函数来实现。 C#中是否有等价物, 或者如果没有,我该如何以另一种方式实现这一目标?

【问题讨论】:

  • 我认为可以从 C# 轻松调用 C 代码。您可以简单地调用一个从 C# 库中设置 FPU 舍入模式的 C 存根。舍入模式在处理器内设置,并将影响 CPU 从该点开始执行的所有浮点计算。
  • 是否需要将C++代码编译成dll文件,然后链接到我的C#程序?
  • 永远不要修改 C# 中的 FPU 控制字。这是你能想象到的最糟糕的全局变量。由于全局变量导致的标准痛苦,您的更改无法持续并且会任意消失。 CLR 中的内部异常处理代码在处理异常时将其重置。
  • @Hans 如果你能给出一些关于设置内部舍入模式的不同方法(特别是舍入小数类型)的提示。例如:setroundmode( DOWNWARD ); var result = 2.0m/3.0m; // result expected: 0.66666666, actual result: 0.66666667 我真的很感激任何方式,因为就像你说的那样,当前的方法不适合 c# - 事实上,尽管我确定我已经创建了它,但它根本不起作用具有正确方法实现的有效 dll 库。
  • System.Decimal 数学是软件完成的,FPU 舍入模式不影响它。它没有舍入控制。

标签: c# c++ floating-point rounding


【解决方案1】:

我按照 Pascal Cuoq 的建议创建了一个非常简单的 - 一个函数程序集。 如果其他人遇到这样的问题,我会在这里发布。

使用我的库的解决方案:

  1. 从以下位置下载 dll 文件:https://www.dropbox.com/s/o3vfxe4rpefhly7/RoundModeUtil.dll
  2. 在您的项目中添加对库的引用。
  3. 包括使用 RoundModeUtils;项目代码中的一行。
  4. 用法:

    static void RoundModeConfig::setround( int mode );
    
    // mode can be set to one of the following values: 
    static int RoundModeConfig::UPWARD
    static int RoundModeConfig::DOWNWARD
    static int RoundModeConfig::DEFAULT     // To nearest mode.
    static int RoundModeConfig::TOWARDZERO
    

感谢 Hans Passant 的建议,我应该记住它。 感谢大家的帮助,希望有人会发现我的 dll 有用:)

【讨论】:

  • 你还有那个dll吗?目前正在从事同一个项目。
【解决方案2】:

对于窗户:

/// <remarks>
/// https://en.cppreference.com/w/cpp/numeric/fenv/FE_round
/// </remarks>
public enum RoundMode
{
    /// <summary>
    /// Rounding towards nearest representable value.
    /// </summary>
    FE_TONEAREST = 0x00000000,

    /// <summary>
    /// Rounding towards negative infinity.
    /// </summary>
    FE_DOWNWARD = 0x00000100,

    /// <summary>
    /// Rounding towards positive infinity.
    /// </summary>
    FE_UPWARD = 0x00000200,

    /// <summary>
    /// Rounding towards zero.
    /// </summary>
    FE_TOWARDZERO = 0x00000300,
}


public static class ExternMethods
{
    [DllImport("ucrtbase.dll", EntryPoint = "fegetround", CallingConvention = CallingConvention.Cdecl)]
    public static extern RoundMode GetRound();

    [DllImport("ucrtbase.dll", EntryPoint = "fesetround", CallingConvention = CallingConvention.Cdecl)]
    public static extern int SetRound(RoundMode roundingMode);
}

【讨论】:

    猜你喜欢
    • 2022-01-09
    • 2010-11-09
    • 1970-01-01
    • 2019-09-29
    • 1970-01-01
    • 1970-01-01
    • 2021-04-30
    • 2017-01-01
    • 2023-03-30
    相关资源
    最近更新 更多