Mdx Sum возвращает нецелое значение - PullRequest
2 голосов
/ 08 февраля 2012

Когда в работе возникает проблема, когда значение, возвращаемое функцией SUM (), не обрабатывается как «нормальное» число при использовании значения, возвращенного вместе с функцией Round ().

Попробуйте этот MDX, например

WITH 
MEMBER SomeNumber AS 0.595 
SET SomeNumberSet AS 
           {[SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber] }

MEMBER SomeNumberSum AS
Round(SUM([SomeNumberSet], [Measures].[SomeNumber]) / 8, 2)


SELECT [SomeNumberSum] ON 0

FROM [SomeCube]

Этот код возвращает 0,59, сумма наборов составляет 4,76, которые затем делятся на 8 = 0,595. Поскольку MDX использует округление банкиров, СЛЕДУЕТ округлить до 0,60.

Использование раунда (0,595) дает нам правильный результат.

Что еще более странно, так это то, что если мы в наборе используем SomeNumber только 6 раз или меньше, а при делении функции раунда с тем же множителем мы получим 0,6 (что правильно)

Кроме того, если я обертываю Sum () с помощью функции StrToValue (), она работает, даже если я использую более 5 SomeNumbers в наборе

Что происходит?!

Ответы [ 2 ]

3 голосов
/ 14 февраля 2012

Не уверен, что именно тот ответ, который вы ищете. Проблема, которую вы должны решить с точностью до чисел, то есть с ошибками округления, больше, чем с MDX.

Если вы находитесь на Java, запустите следующий тест:

public void testNumeric()
{
    double sum = 0.0;
    double value = 0.595;

    for (int i = 0; i < 8; i++)
    {
        sum += value;
    }

    double prod = value * 8;
    assertEquals(sum / 8, prod / 8);
}

Утверждение не удастся, странно, нет?

Result : expected:<0.5949999999999999> but was:<0.595>

Первый, сумма, это то, как MDX вычисляет значение. Вы получили небольшую разницу, но этого достаточно для изменения результата от ROUND ().

Есть ли решение?

Строго говоря, нет, это ошибка из-за самой природы численных расчетов с компьютерами. Практически вы можете немного обмануть раунд до 10 - КРУГЛЫЙ (КРУГЛЫЙ (MyNumber, 10), 2), не бриллиант (например, 10).

Если вам интересно, начните википедию с здесь

0 голосов
/ 08 февраля 2012

Согласно Крису Уэббу, такое поведение является преднамеренным:

http://www.techonthenet.com/access/functions/numeric/round.php

Если у вас есть библиотеки Excel, это работает:

WITH 
MEMBER SomeNumber AS 0.595 
SET SomeNumberSet AS 
           {[SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber], [SomeNumber] }

MEMBER SomeNumberSum AS
Excel!Round(SUM([SomeNumberSet], [Measures].[SomeNumber]) / 8, 2)

SELECT [SomeNumberSum] ON 0
FROM [Adventure Works]
...