Парадокс розподілу


10

Подано:

  • Натуральне число S .
  • Список N раціональних ваг W, що дорівнює 1.

Поверніть список L з N негативних чисел, таким чином:

(1) sum(L) = S
(2) sum((S⋅W_i - L_i)^2) is minimal

Іншими словами, наближайте S⋅W_is до цілих чисел якомога ближче.

Приклади:

1 [0.4 0.3 0.3] = [1 0 0]
3 [0 1 0] = [0 3 0]
4 [0.3 0.4 0.3] = [1 2 1]
5 [0.3 0.4 0.3] = [2 2 1] or [1 2 2] but not [1 3 1]
21 [0.3 0.2 0.5] = [6 4 11]
5 [0.1 0.2 0.3 0.4] = [1 1 1 2] or [0 1 2 2]
4 [0.11 0.3 0.59] = [1 1 2]
10 [0.47 0.47 0.06] = [5 5 0]
10 [0.43 0.43 0.14] = [4 4 2]
11 [0.43 0.43 0.14] = [5 5 1]

Правила:

  • Ви можете взагалі використовувати будь-який формат введення або просто надати функцію, яка приймає дані як аргументи.

Фон:

Ця проблема виникає при відображенні S різних типів предметів у різних пропорціях W i щодо типів.

Інший приклад цієї проблеми - пропорційне політичне представництво, див. Парадокс розподілу . Останні два тестові випадки відомі як парадокс Алабами.

Як статистик я визнав цю проблему еквівалентною проблемі, що виникає при визначенні розмірів вибірки при проведенні стратифікованої вибірки. У цій ситуації ми хочемо зробити частку кожного прошарку у вибірці рівній частці кожного прошарку в сукупності. - @tomi


Не могли б ви сказати словами, що це за завдання? У мене виникають проблеми з декомпресією виразів на щось інтуїтивне.
xnor

Обидва повинні бути ≤, зафіксовані. Завдання полягає в поданні цілого числа у вигляді суми цілих чисел на основі ваг. Залишок повинен розподіляти на користь найвищих ваг, хоча я не впевнений, що ця вимога закодована правильно? Це цікаво тим round(A + B) != round(A) + round(B), що коротке рішення вимагає розуміння того, що тут відбувається.
Глебм

1
Можливо, змініть правила, щоб мінімізувати суму L[i] - S*W[i]квадратів відстаней , замість правила 2 та правила 3. Це буде приблизним S*W[i].
Якубе

1
Також [0 1 2 2] є ще одне можливе рішення для5 [0.1 0.2 0.3 0.4]
Jakube

1
Можливо, ви повинні додати приклад для 1 [0,4 0,3 0,3]
aditsu кинути, тому що SE - EVIL

Відповіді:


6

APL, 21

{{⍵+1=⍋⍋⍵-⍺}⍣⍺/⍺0×⊂⍵}

Це переклад із відповіді CJam на 37 байт aditsu .

Перевірте це в Інтернеті .

Пояснення

 {      ⍵-⍺}            ⍝ Right argument - left argument.
 {  1=⍋⍋⍵-⍺}            ⍝ Make one of the smallest number 1, others 0.
 {⍵+1=⍋⍋⍵-⍺}            ⍝ Add the result and the right argument together.
 {⍵+1=⍋⍋⍵-⍺}⍣⍺          ⍝ Repeat that S times. The result of each iteration is the new right argument.
                  ⊂⍵    ⍝ Return enclosed W, which is taken as one unit in APL.
               ⍺0×⊂⍵    ⍝ Return S*W and 0*W.
{{⍵+1=⍋⍋⍵-⍺}⍣⍺/⍺0×⊂⍵}   ⍝ Make S*W the left argument, 0*W the right argument in the first iteration.

7

Пітон 2, 95 83 132 125 143 143

У мого першого (і другого) (і третього) алгоритму виникли проблеми, тому після (чергового!) Переписування та більше тестування, ось (я дуже сподіваюся) правильне і швидке рішення:

def a(b,h):
 g=h;c=[];d=[]
 for w in b:f=int(w*h);d+=[f];c+=[h*w-f];g-=f
 if g:
  for e in sorted(c)[-g:]:i=c.index(e);c[i]=2;d[i]+=1
 return d

Джерело перед мініфікатором зараз виглядає так:

# minified 143 bytes
def golfalloc(weights, num):
    # Tiny seq alloc for golfing
    gap = num;
    errors = [];
    counts = []
    for w in weights :
        count = int(w*num);
        counts += [count];
        errors += [num*w - count];
        gap -= count
    if gap:
        for e in sorted(errors)[-gap:] :
            i = errors.index(e);
            errors[i] = 2;
            counts[i] += 1
    return counts

Тести повертаються:

Pass                    Shape    N               Result Error                        AbsErrSum
ok            [0.4, 0.3, 0.3]    1            [1, 0, 0] -0.60,+0.30,+0.30                 1.20
ok                  [0, 1, 0]    3            [0, 3, 0] +0.00,+0.00,+0.00                 0.00
ok            [0.3, 0.4, 0.3]    4            [1, 2, 1] +0.20,-0.40,+0.20                 0.80
ok            [0.3, 0.4, 0.3]    5            [2, 2, 1] -0.50,+0.00,+0.50                 1.00
ok            [0.3, 0.2, 0.5]   21           [6, 4, 11] +0.30,+0.20,-0.50                 1.00
ok       [0.1, 0.2, 0.3, 0.4]    5         [1, 1, 1, 2] -0.50,+0.00,+0.50,+0.00           1.00
ok          [0.11, 0.3, 0.59]    4            [1, 1, 2] -0.56,+0.20,+0.36                 1.12
ok         [0.47, 0.47, 0.06]   10            [5, 5, 0] -0.30,-0.30,+0.60                 1.20
ok         [0.43, 0.43, 0.14]   10            [4, 4, 2] +0.30,+0.30,-0.60                 1.20
ok         [0.43, 0.43, 0.14]   11            [5, 5, 1] -0.27,-0.27,+0.54                 1.08

Цей алгоритм схожий на інші відповіді тут. Це число O (1) для num, тому він має однаковий час виконання для цілих чисел 10 і 1000000. Теоретично це O (nlogn) для кількості ваг (через сортування). Якщо це витримує всі інші складні випадки введення, воно замінить алгоритм, наведений нижче, в моїй панелі інструментів програмування.

Будь ласка, не використовуйте цей алгоритм ні з чим, не гофрованим. Я робив компроміси у швидкості, щоб мінімізувати розмір джерела. Наступний код використовує ту ж логіку, але набагато швидший і корисніший:

def seqalloc(anyweights, num):
    # Distribute integer num depending on weights.
    # weights may be non-negative integers, longs, or floats.
    totalbias = float(sum(anyweights))
    weights = [bias/totalbias for bias in anyweights]
    counts = [int(w*num) for w in weights]
    gap = num - sum(counts)
    if gap:
        errors = [num*w - q for w,q in zip(weights, counts)]
        ordered = sorted(range(len(errors)), key=errors.__getitem__)
        for i in ordered[-gap:]:
            counts[i] += 1
    return counts

Значення num не впливає суттєво на швидкість. Я перевірив це зі значеннями від 1 до 10 ^ 19. Час виконання змінюється лінійно залежно від кількості ваг. На моєму комп’ютері це займає 0,15 секунди з 10 ^ 5 вагами і 15 секунд з 10 ^ 7 вагами. Зверніть увагу, що ваги не обмежуються дробами, які дорівнюють одиниці. Техніка сортування, яка використовується тут, також приблизно вдвічі швидша, ніж традиційний sorted((v,i) for i,v in enumerate...)стиль.

Оригінальний алгоритм

Це була функція в моєму наборі інструментів, трохи модифікованому для гольфу. Це було спочатку з відповіді на відповідь . І це неправильно.

def seqalloc(seq, num):
    outseq = []
    totalw = float(sum(seq))
    for weight in seq:
        share = int(round(num * weight / totalw)) if weight else 0
        outseq.append(share)
        totalw -= weight
        num -= share
    return outseq

Це дає наближення, але не завжди є правильним, хоча сума (outseq) == число зберігається. Швидкий, але не рекомендується.

Дякуємо @alephalpha та @ user23013 за виявлення помилок.

EDIT: Встановіть totalw (d) рівним 1, оскільки OP визначає, що сума ваг завжди буде 1. Тепер 83 байти.

EDIT2: виправлена ​​помилка, знайдена для [0,4, 0,3, 0,3], 1.

EDIT3: Покинутий недосконалий алгоритм. Додано кращий.

EDIT4: Це стає смішним. Замінено правильним (я дуже сподіваюсь) алгоритмом.

EDIT5: Додано незавершений код для інших, які можуть хотіти використовувати цей алгоритм.


4
a([0.4, 0.3, 0.3], 1)повертається [0, 1, 0], а правильна відповідь [1, 0, 0].
алефальфа

1
Досі помиляюся. a([0.11,0.3,0.59],4)повернувся [0, 1, 3]. Повинно бути [1, 1, 2].
jimmy23013

1
f([0.47,0.47,0.06],10)повернувся [5, 4, 1]. Повинно бути [5, 5, 0].
jimmy23013

2
Я думаю, це зараз правильно.
jimmy23013

2
@CarpetPython Я пройшов подібний процес з цим алгоритмом, і ось як я вирішив цю проблему. Якщо вони відберуть вашу ліцензію, вони теж повинні забрати мою :)
glebm

4

Математика, 67 50 46 45 символів

f=(b=⌊1##⌋;b[[#~Ordering~-Tr@#&[b-##]]]++;b)&

Безголівки:

f[s_, w_] := Module[{a = s*w, b, c, d},
  b = Floor[a];
  c = b - a;
  d = Ordering[c, -Total[c]];
  b[[d]] += 1;
  b]

Приклад:

f[5,{0.1,0.2,0.3,0.4}]

{1, 1, 1, 2}


Боже мій, це коротко, враховуючи, що це Mathematica!
DavidC

3

CJam - 37

q~:W,0a*\:S{[_SWf*]z::-_:e<#_2$=)t}*p

Спробуйте в Інтернеті

Пояснення:

q~             read and evaluate the input
               (pushing the number and the array on the stack)
:W,            save the array in variable W and calculate its length (N)
0a*            make an array of N zeros (the initial "L")
\:S            swap it with the number and save the number in S
{…}*           execute the block S times
    [_SWf*]    make a matrix with 2 rows: "L" and S*W
    z          transpose the matrix, obtaining rows of [L_i S*W_i]
    ::-_       convert to array of L_i-S*W_i and duplicate
    :e<        get the smallest element
    #          find its index in the unsorted array,
               i.e. the "i" with the largest S*W_i-L_i
    _2$=)t     increment L_i
p              print the result nicely

Примітки:

  • Складність становить близько O (S * N), тому він стає дуже повільним для великих S
  • CJam дуже не вистачає арифметичних операторів для 2-х масивів, що я планую реалізувати пізніше

Інша ідея - 46

q~:Sf*_:m[_:+S\-@[1f%_,,]z{0=W*}$<{1=_2$=)t}/p

Спробуйте в Інтернеті

Це набагато простіше та ефективніше, але, на жаль, зовсім трохи довше. Ідея тут - почати з L_i = floor (S * W_i), визначити різницю (скажімо D) між S та їх сумою, знайти індекси D з найбільшою частковою частиною S * W_i (сортуючи та беручи верхню D) і збільшення L_i для цих індексів. Складність O (N * log (N)).


Зараз є O (N) :e<.
jimmy23013

@ user23013 о так, за першу програму, спасибі
aditsu кинь, тому що SE EVIL

Це було швидко! Поздравляю 🌟
глебм

Для тих, хто цікавиться, заміна сортування алгоритмом лінійного вибору часу дасть O (n) замість фактичного O (nlogn), викликаного сортуванням: Знайдіть D-й найбільший елемент, P, в O (N), а потім приріст елементи, що ≥PD-раз (O (N), оскільки D <= N).
Глебм

@glebm це досить круто, але я думаю, що існує проблема, якщо кілька елементів мають однакове значення (P). Можливо, ви зможете вирішити це за 2 проходи тоді: спочатку зросте і порахуйте елементи> P, потім ви знаєте, скільки елементів = P потрібно. Або якщо ви можете отримати цю інформацію з алгоритму вибору, ще краще.
aditsu кинути, тому що SE

3

JavaScript (ES6) 126 130 104 115 156 162 194

Після всіх коментарів та тестових випадків у відповіді @ CarpetPython, повернутися до мого першого алгоритму. На жаль, розумне рішення не працює. Реалізація трохи скоротилася, вона все ще намагається виконати всі можливі рішення, прорахувати відстань у квадраті та дотримати мінімум.

Редагувати Для кожного вихідного елемента вагою w "усі" можливі значення - це лише 2: trunc (w * s) і trunc (w * s) +1, тому є просто (2 ** елементасти) можливі рішення.

Q=(s,w)=>
  (n=>{
    for(i=0;
        r=q=s,(y=i++)<1<<w.length;
        q|r>n||(n=r,o=t))
      t=w.map(w=>(f=w*s,q-=d=0|f+(y&1),y/=2,f-=d,r+=f*f,d));
  })()||o

Тест у консолі Firefox / FireBug

;[[ 1,  [0.4, 0.3, 0.3]      ]
, [ 3,  [0, 1, 0]            ]
, [ 4,  [0.3, 0.4, 0.3]      ]
, [ 5,  [0.3, 0.4, 0.3]      ]
, [ 21, [0.3, 0.2, 0.5]      ]
, [ 5,  [0.1, 0.2, 0.3, 0.4] ]
, [ 4,  [0.11, 0.3, 0.59]    ]
, [ 10, [0.47, 0.47, 0.06]   ]
, [ 10, [0.43, 0.43, 0.14]   ]
, [ 11, [0.43, 0.43, 0.14]   ]]
.forEach(v=>console.log(v[0],v[1],Q(v[0],v[1])))

Вихідні дані

1 [0.4, 0.3, 0.3] [1, 0, 0]
3 [0, 1, 0] [0, 3, 0]
4 [0.3, 0.4, 0.3] [1, 2, 1]
5 [0.3, 0.4, 0.3] [1, 2, 2]
21 [0.3, 0.2, 0.5] [6, 4, 11]
5 [0.1, 0.2, 0.3, 0.4] [0, 1, 2, 2]
4 [0.11, 0.3, 0.59] [1, 1, 2]
10 [0.47, 0.47, 0.06] [5, 5, 0]
10 [0.43, 0.43, 0.14] [4, 4, 2]
11 [0.43, 0.43, 0.14] [5, 5, 1]

Це розумніше рішення. Одномісний прохід по масиву ваг.
Для кожного проходу я знаходжу поточне максимальне значення в w. Я змінюю це значення замість зваженого цілого значення (округлюється вгору), тому, якщо s == 21 і w = 0,4, ми отримаємо 0,5 * 21 -> 10,5 -> 11. Я зберігаю це значення заперечуваним, тому воно не може буде знайдено як max у наступному циклі. Тоді я відповідно зменшую загальну суму (s = s-11), а також зменшую загальну вагу у змінній f.
Цикл закінчується, коли термін не перевищує максимум 0 (усі значення! = 0 керовані).
Нарешті я знову повертаю змінені значення на позитивні. Попередження цього коду змінює масив ваг на місці, тому його потрібно викликати з копією оригінального масиву

F=(s,w)=>
 (f=>{
  for(;j=w.indexOf(z=Math.max(...w)),z>0;f-=z)
    s+=w[j]=-Math.ceil(z*s/f);
 })(1)||w.map(x=>0-x)

Моя перша спроба

Не таке розумне рішення. Для кожного можливого результату він оцінює різницю і зберігає мінімум.

F=(s,w,t=w.map(_=>0),n=NaN)=>
  (p=>{
    for(;p<w.length;)
      ++t[p]>s?t[p++]=0
      :t.map(b=>r+=b,r=p=0)&&r-s||
        t.map((b,i)=>r+=(z=s*w[i]-b)*z)&&r>n||(n=r,o=[...t])
  })(0)||o

Непорочний І пояснив

F=(s, w) =>
{
  var t=w.map(_ => 0), // 0 filled array, same size as w
      n=NaN, // initial minumum NaN, as "NaN > value"  is false for any value
      p, r
  // For loop enumerating from [1,0,0,...0] to [s,s,s...s]
  for(p=0; p<w.length;)
  {
    ++t[p]; // increment current cell
    if (t[p] > s)
    {
      // overflow, restart at 0 and point to next cell
      t[p] = 0;
      ++p;
    }
    else
    {
      // increment ok, current cell is the firts one
      p = 0;
      r = 0;
      t.map(b => r += b) // evaluate the cells sum (must be s)
      if (r==s)
      {
        // if sum of cells is s
        // evaluate the total squared distance (always offset by s, that does not matter)
        t.map((b,i) => r += (z=s*w[i]-b)*z) 
        if (!(r > n))
        {
          // if less than current mininum, keep this result
          n=r
          o=[...t] // copy of t goes in o
        }
      }
    }
  }
  return o
}

2

CJam, 48 байт

Безпосереднє рішення проблеми.

q~:Sf*:L,S),a*{m*{(+}%}*{1bS=},{L]z::-Yf#:+}$0=p

Введення іде як

[0.3 0.4 0.3] 4

Пояснення:

q~:S                                 "Read and parse the input, store sum in S";
    f*:L                             "Do S.W, store the dot product in L";
         S),                         "Get array of 0 to S";
        ,   a*                       "Create an array with N copies of the above array";
              {m*{(+}%}*             "Get all possible N length combinations of 0 to S ints";
                        {1bS=},      "Filter to get only those which sum up to S";
{L]z::-Yf#:+}$                       "Sort them based on (S.W_i - L_i)^2 value";
 L                                   "Put the dot product after the sum combination";
  ]z                                 "Wrap in an array and transpose";
    ::-                              "For each row, get difference, i.e. S.W_i - L_i";
       Yf#                           "Square every element";
          :+                         "Take sum";
              0=p                    "After sorting on sum((S.W_i - L_i)^2), take the";
                                     "first element, i.e. smallest sum and print it";

Спробуйте його онлайн тут


2

Pyth: 40 байт

Mhosm^-*Ghded2C,HNfqsTGmms+*G@Hb}bklHyUH

Це визначає функцію gз 2 параметрами. Ви можете назвати це як Mhosm^-*Ghded2C,HNfqsTGmms+*G@Hb}bklHyUHg5 [0.1 0.2 0.3 0.4.

Спробуйте в Інтернеті: компілятор / виконавець Pyth

Пояснення:

mms+*G@Hb}bklHyUH     (G is S, H is the list of weights)
m             yUH    map each subset k of [0, 1, ..., len(H)-1] to:
 m          lH          map each element b of [0, 1, ..., len(H)-1] to: 
    *G@Hb                  G*H[b]
   +     }bk               + b in k
  s                       floor(_)

Це створює всі можливі рішення L, де L[i] = floor(S*W[i])або L[i] = floor(S*W[i]+1). Наприклад, вхід 4 [0.3 0.4 0.3створює [[1, 1, 1], [2, 1, 1], [1, 2, 1], [1, 1, 2], [2, 2, 1], [2, 1, 2], [1, 2, 2], [2, 2, 2]].

fqsTG...  
f    ... only use the solutions, where
 qsTG       sum(solution) == G

[[2, 1, 1], [1, 2, 1], [1, 1, 2]]Залишаються лише .

Mhosm^-*Ghded2C,HN
  o                  order the solutions by
   s                   the sum of 
    m         C,HN       map each element d of zip(H, solution) to
     ^-*Ghded2           (G*d[0] - d[1])^2
 h                   use the first element (minimum)
M                    define a function g(G,H): return _

2

Математика 108

s_~f~w_:=Sort[{Tr[(s*w-#)^2],#}&/@ 
Flatten[Permutations/@IntegerPartitions[s,{Length@w},0~Range~s],1]][[1,2]]

f[3, {0, 1, 0}]
f[4, {0.3, 0.4, 0.3}]
f[5, {0.3, 0.4, 0.3}]
f[21, {0.3, 0.2, 0.5}]
f[5, {0.1, 0.2, 0.3, 0.4}]

{0, 3, 0}
{1, 2, 1}
{1, 2, 2}
{6, 4, 11}
{0, 1, 2, 2}


Пояснення

Безумовно

f[s_,w_]:=
Module[{partitions},
partitions=Flatten[Permutations/@IntegerPartitions[s,{Length[w]},Range[0,s]],1];
Sort[{Tr[(s *w-#)^2],#}&/@partitions][[1,2]]]

IntegerPartitions[s,{Length@w},0~Range~s]повертає всі цілі розділи s, використовуючи елементи, взяті з множини {0, 1, 2, ...s}з обмеженням, що вихід повинен містити таку ж кількість елементів, як у наборі ваг,w .

Permutations дає всі впорядковані розташування кожного цілого розділу.

{Tr[(s *w-#)^2],#}повертає список упорядкованих пар {error, permutation} для кожної перестановки.

Sort[...] сортує список {{error1, permutation1},{error2, permutation2}...according to the size of the error.

[[1,2]]]або Part[<list>,{1,2}]повертає другий елемент першого елемента в упорядкованому списку {{error, permutation}...}. Іншими словами, він повертає перестановку з найменшою помилкою.


2

R, 85 80 76

Використовує метод квоти зайця.

Вилучили пару після того, як побачили специфікацію, що W складе 1

function(a,b){s=floor(d<-b*a);s[o]=s[o<-rev(order(d%%1))[0:(a-sum(s))]]+1;s}

Тестовий запуск

> (function(a,b){s=floor(d<-b/(sum(b)/a));s[o]=s[o<-rev(order(d%%1))[0:(a-sum(s))]]+1;s})(3,c(0,1,0))
[1] 0 3 0
> (function(a,b){s=floor(d<-b/(sum(b)/a));s[o]=s[o<-rev(order(d%%1))[0:(a-sum(s))]]+1;s})(1,c(0.4,0.3,0.3))
[1] 1 0 0
> (function(a,b){s=floor(d<-b/(sum(b)/a));s[o]=s[o<-rev(order(d%%1))[0:(a-sum(s))]]+1;s})(4,c(0.3, 0.4, 0.3))
[1] 1 2 1
> (function(a,b){s=floor(d<-b/(sum(b)/a));s[o]=s[o<-rev(order(d%%1))[0:(a-sum(s))]]+1;s})(5,c(0.3, 0.4, 0.3))
[1] 1 2 2
> (function(a,b){s=floor(d<-b/(sum(b)/a));s[o]=s[o<-rev(order(d%%1))[0:(a-sum(s))]]+1;s})(21,c(0.3, 0.2, 0.5))
[1]  6  4 11
> (function(a,b){s=floor(d<-b/(sum(b)/a));s[o]=s[o<-rev(order(d%%1))[0:(a-sum(s))]]+1;s})(5,c(0.1,0.2,0.3,0.4))
[1] 1 1 1 2
>

2

Пітон, 139 128 117 байт

def f(S,W):
 L=(S+1,0,[]),
 for n in W:L=[(x-i,y+(S*n-i)**2,z+[i])for x,y,z in L for i in range(x)]
 return min(L)[2]

Попереднє рішення itertools, 139 байт

from itertools import*
f=lambda S,W:min((sum(x)!=S,sum((S*a-b)**2for a,b in zip(W,x)),list(x))for x in product(*tee(range(S+1),len(W))))[2]

Мені було цікаво, чи можливе рішення itertools. Приємна робота +1. Я маю рацію, думаючи, що ця складність у часі має O (n ^ 4)?
Логічний лицар

Рішення Itertools було O(S^len(W))насправді: P. Нове рішення набагато швидше, але все ж повільне
Sp3000

2

Октава, 87 76

Гольф:

function r=w(s,w)r=0*w;for(i=1:s)[m,x]=max(s*w-r);r(x)+=1;endfor endfunction

Безголівки:

function r=w(s,w)
  r=0*w;   # will be the output
  for(i=1:s)
    [m,x]=max(s*w-r);
    r(x)+=1;
  endfor
endfunction

(Вибух "ендфор" і "ендфункція"! Я ніколи не виграю, але люблю гольф "справжньою" мовою.)


Гарний алгоритм. Ви можете замінити zeros(size(w))на 0*w.
алефальфа

Приємно! Чому я не придумав цього?
dcsohl

1

T-SQL, 167 265

Тому що я люблю намагатися виконувати ці завдання і в запиті.

Перетворив його на вбудовану функцію, щоб краще відповідати специфікації та створив тип для даних таблиці. Це коштувало трохи, але це ніколи не буде суперником. Кожен оператор потрібно запускати окремо.

CREATE TYPE T AS TABLE(A INT IDENTITY, W NUMERIC(9,8))
CREATE FUNCTION W(@ int,@T T READONLY)RETURNS TABLE RETURN SELECT CASE WHEN i<=@-SUM(g)OVER(ORDER BY(SELECT\))THEN g+1 ELSE g END R,A FROM(SELECT A,ROW_NUMBER()OVER(ORDER BY (W*@)%1 DESC)i,FLOOR(W*@)g FROM @T)a

В вживанні

DECLARE @ INT = 21
DECLARE @T T
INSERT INTO @T(W)VALUES(0.3),(0.2),(0.5)
SELECT R FROM dbo.W(@,@T) ORDER BY A

R
---------------------------------------
6
4
11
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.