English 中文(简体)
如何使我的广度浮动点更加高效?
原标题:How to make my extended range floating point multiply more efficient?

I am doing a calculation which frequently involves values like 3.47493E+17298. This is way beyond what a double can handle, and I don t need extra precision, just extra range of exponents, so I created my own little struct in C#.

我的 st用了很长的时间,可以用来表示和签署,也可以是旁观,因此我实际上已经:

1 sign bit 32 exponent bits (regular 2 s complement exponent) 63 significand bits

我奇怪的是,可以采取哪些步骤,使我的多彩工作更加日常有效。 我正在追随这些扩展范围价值的大量繁多之处,而且很快,但我正在寻找使这一范围更快的方面。

My multiplication routine:

    public static BigFloat Multiply(BigFloat left, BigFloat right)
    {
        long shsign1;
        long shsign2;

        if (left.significand == 0)
        {
            return bigZero;
        }

        if (right.significand == 0)
        {
            return bigZero;
        }

        shsign1 = left.significand;
        shsign2 = right.significand;

        // scaling down significand to prevent overflow multiply

        // s1 and s2 indicate how much the left and right 
        // significands need shifting.
        // The multLimit is a long constant indicating the
        // max value I want either significand to be
        int s1 = qshift(shsign1, multLimit);
        int s2 = qshift(shsign2, multLimit);

        shsign1 >>= s1;
        shsign2 >>= s2;

        BigFloat r;

        r.significand = shsign1 * shsign2;
        r.exponent = left.exponent + right.exponent + s1 + s2;

        return r;
    }

And the qshift:

It just finds out how much to shift the val to make it smaller in absolute value than the limit.

    public static int qshift(long val, long limit)
    {
        long q = val;
        long c = limit;
        long nc = -limit;

        int counter = 0;

        while (q > c || q < nc)
        {
            q >>= 1;
            counter++;
        }

        return counter;
    }
问题回答

这里的想法完全不同。

使用硬件浮点机械,但用你自己的喷气机加以扩充。 另一种方式,即<代码> BigFloat.significand 是浮动点数,而不是星号。

然后,您可使用<代码>ldexp和frexp,使浮标上的实际权势保持在零。 这些指示应为单一机器指示。

因此,大饥荒成倍:

  • r.significand = left.significand * right.significand
  • r.exponent = left.exponent + right.exponent
  • tmp = (actual exponent of r.significand from frexp)
  • r.exponent += tmp
  • (use ldexp to subtract tmp from actual exponent of r.significand)

不幸的是,最后两个步骤要求<代码>frexp和ldexp,这些查询建议无法在C#中查阅。 因此,你可能不得不在C处写这一字句。

......

或者,实际.........

信号器使用浮点号码,但只是将其固定在1至2之间。 同样,使用信号灯的浮标,并成倍:

r.significand = left.significand * right.significand;
r.exponent = left.exponent + right.exponent;
if (r.significand >= 2) {
    r.significand /= 2;
    r.exponent += 1;
}
assert (r.significand >= 1 && r.significand < 2);  // for debugging......

只要你坚持主张中所提到的无所作为,就应当这样做。 (由于x在1至2之间, y在1至2之间,x*y在1至4之间,因此,在标识产品在2至4之间时,必须检查正常化步骤)

你们也需要使增补结果正常化,但我怀疑你已经这样做。

虽然你在以下几段之后需要特别的零件。

[编辑,以充实<代码>frexp版本]

BigFloat BigFloat::normalize(BigFloat b)
{
    double temp = b.significand;
    double tempexp = b.exponent;
    double temp2, tempexp2;
    temp2 = frexp(temp, &tempexp2);
    // Need to test temp2 for infinity and NaN here
    tempexp += tempexp2;
    if (tempexp < MIN_EXP)
        // underflow!
    if (tempexp > MAX_EXP)
        // overflow!
    BigFloat r;
    r.exponent = tempexp;
    r.significand = temp2;
}

换言之,我建议将此列为“正常”做法,因为大概在增加、减小、重复和分裂之后,你希望加以利用。

那么,所有角落都担心......。...

你也许希望通过零回来处理流入不足的问题。 溢出取决于您的口味;这要么是一种错误,要么是+-finity。 最后,如果(vexp)的结果是肯定的,或N,那么tempexp<2>/code”的价值就没有界定,因此,你可能也要检查这些案件。

我不是C#方案家,但这里有一些一般的想法。

第一,C#是否有任何分析工具? 如果是,从......开始。

时间很可能用于您的班轮工作,特别是休息时间。 错误的分支是新生的。

I would rewrite it as:

long q = abs(val);
int x = q/nc;
(find next power of 2 bigger than x)

For that last step, see this question and answer.

Then instead of shifting by qshift, just divide by this power of 2. (Does C# have "find first set" (aka. ffs)? If so, you can use it to get the shift count from the power of 2; it should be one instruction.)

Definitely inline this sequence if the compiler will not do it for you.

此外,除非你将“<>>>>>>成倍”,否则我将将特例搁置为零。 密码良好;条件差。





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...