Как я могу преобразовать десятичное число в часть?

Сообщение об ошибке вызвано тем, что тип btnWrap boolean не соответствует типу индекса строки string. Тип {[key: string]: string, btnWrap: boolean}} пытается сказать, что каждое свойство имеет строковое значение и , что btnWrap имеет логическое значение. Оба не могут быть правдой, поэтому компилятор предупреждает вас.


Нет ни одного конкретного типа MyObj, который представлял бы ограничение, как вы его описали. Но вы можете создать универсальный тип , который принимает объединение ключевых литералов K и создает тип MyObj:

type MyObj = 
  { [P in K]: string | (Record & { btnWrap: boolean }) };

Тип MyObj ] является отображенным типом , где каждое свойство с ключом P имеет либо тип значения string, либо пересечение из {btnWrap: boolean} с Record. Последний тип сам по себе является отображенным типом (, определенным в стандартной библиотеке ) с ключами P и свойствами string. Таким образом, каждое свойство MyObject должно выглядеть как someKey: string или someKey: {btnWrap: boolean, someKey: string}.

Опять же, чтобы описать тип myObj, вместо чего-то простого, такого как let myObj: MyObj = ..., вы должны сделать что-то вроде let myObj: MyObj<"key1"|"key2"|"key3"> = ..., где вы указываете общие параметры. Чтобы вам не пришлось делать это самостоятельно, вы можете использовать универсальную вспомогательную функцию, чтобы помочь вывести тип K данного объекта, например:

[111 ]

Теперь давайте попробуем:

let myObj1 = asMyObj({ key1: 'val1', key2: 'val2', key3: 'val3' });
let myObj2 = asMyObj({ key1: 'val1', key2: { key2: 'val2', btnWrap: true }, key3: 'val3' });

Те работают просто отлично. Теперь давайте посмотрим, что пойдет не так, если вы нарушите свое ограничение:

let badMyObj1 = asMyObj({ key1: 1 }); 
// error, number is bad

let badMyObj2 = asMyObj({ key1: "val1", key2: { key2: "val2" } }); 
// error, missing btnWrap

let badMyObj3 = asMyObj({ key1: "val1", key2: { btnWrap: true } }); 
// error, missing key2 inside value

let badMyObj4 = asMyObj({ key1: "val1", key2: { key3: "val3", btnWrap: true } }); 
// error, key3 not expected inside value

Эти ошибки, вероятно, то, что вы хотите увидеть, верно?


Хорошо, надеюсь, это поможет. Вот ссылка Playground на приведенный выше код. Удачи!

8
задан Brann 1 April 2009 в 17:03
поделиться

11 ответов

Как.333333333 не 1/3, Вы никогда не будете получать 1/3, но вместо этого 333333333/1000000000, если Вы не добавите некоторую умную логику "неокругления".

Вот решение для обработки чисел с периодическим десятичным представлением, которое я помню из школы.

Номер 0.abcdabcd... равняется abcd/9999. Так 0.23572357... равняется 2357/9999 точно. Просто возьмите это многие 9 с, поскольку Ваш шаблон длинен. 0.11111... равняется 1/9, 0.121212... равняется 12/99, и так далее. Так пробуют просто поиск шаблона и установку знаменателя к соответствующему числу. Конечно, необходимо остановиться после некоторых цифр, потому что Вы никогда не будете знать, повторяется ли шаблон навсегда или просто много раз. И Вы поразите погрешность округления в последней цифре, таким образом, Вам все еще будет нужна некоторая умная логика.

18
ответ дан 5 December 2019 в 05:13
поделиться

Google для "десятичного числа для фракционирования" и Вы получите приблизительно огромное количество результатов.

Мне действительно нравится этот, потому что это просто, имеет исходный код (в RPL, подобном Forth, ~25 строкам), и довольно быстро (это записано для работы 4-разрядного, ЦП на 4 МГц). В документах говорится:

В книге под названием Учебник по Алгебре G. Chrystal, 1-й выпуск в 1889, во Второй части, Главе 32, этот улучшенный алгоритм непрерывной дроби представлен и доказан. Нечетный для сообщения Chrystal говорит о нем, как будто это было древнее знание.

2
ответ дан 5 December 2019 в 05:13
поделиться

Этот сайт, кажется, имеет действительно хорошую реализацию этого в JavaScript.

2
ответ дан 5 December 2019 в 05:13
поделиться

Я умножился бы на 10000000 (или независимо от того, что Вы хотите в зависимости от точности), затем упростите получающуюся часть (т.е. n*10000000/10000000)

1
ответ дан 5 December 2019 в 05:13
поделиться

Можно приблизить его. По существу циклически повторяют через все числители и знаменатели, пока Вы не достигаете части, которая является близко к тому, что Вы хотите.

int num = 1;
int den = 1;
double limit == 0.1;
double fraction = num / den;

while(den < 1000000 ) // some arbitrary large denominator
{
    den = den + 1;    
    for(num = 0; num <= den; num++)
    {
        fraction = num / den;
        if(fraction < n + limit && fraction > n - limit)
             return (num + "/" + den);
    }
}

Это медленно и алгоритм грубой силы, но необходимо в общих чертах понять.

1
ответ дан 5 December 2019 в 05:13
поделиться

В целом будет легче при нахождении повторяющейся части рационального числа. Если Вы не можете найти, что, Вам будет нелегко. Скажем, число, если 8.45735735735...

Ответ равняется 8 + 45/100 + 735/999/100 = 8 1523/3330.

Целое число равняется 8. Добавьте 45/100 - который является.45, часть перед повторяющейся частью.

Повторяющаяся часть является 735/999. В целом примите повторяющееся участие. Сделайте это числителем. Знаменатель 10^ (количество повторяющихся цифр) - 1.

Примите повторяющееся участие и сместите его соответствующее количество цифр. В этом случае, два, что означает, делятся на 100, таким образом, 735/999/100.

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

1
ответ дан 5 December 2019 в 05:13
поделиться

Подобный CookieOfFortune, но это находится в VB и не использует в качестве большого количества грубой силы.

Dim tolerance As Double = 0.1   'Fraction has to be at least this close'
Dim decimalValue As Double = 0.125  'Original value to convert'
Dim highestDenominator = 100   'Highest denominator you`re willing to accept'

For denominator As Integer = 2 To highestDenominator - 1
    'Find the closest numerator'
    Dim numerator As Integer = Math.Round(denominator * decimalValue)

    'Check if the fraction`s close enough'
    If Abs(numerator / denominator - decimalValue) <= tolerance Then
        Return numerator & "/" & denominator
    End If
Next

'Didn't find one.  Use the highest possible denominator'
Return Math.Round(denominator * decimalValue) & "/" & highestDenominator

... Сообщите мне, должно ли это составлять значения, больше, чем 1, и я могу скорректировать его.

Править: Извините за проваленную подсветку синтаксиса. Я не могу выяснить, почему это неправильно. Если кто-то знает, как я могу сделать его лучше, сообщите мне.

1
ответ дан 5 December 2019 в 05:13
поделиться

Python имеет хорошую стандартную программу в своем модуле частей. Вот рабочая часть, которая преобразовывает n/d в самое близкое приближение N/D где D <= некоторое максимальное значение. например, если Вы хотите найти самую близкую часть к 0,347, позвольте n=347, d=1000 и max_denominator быть 100, и Вы получите (17, 49), который так близок, как можно добраться для знаменателей, меньше чем или равных 100. '//' оператор является целочисленным делением так, чтобы 2//3 дал 0, т.е.//b = интервал (a/b).

def approxFrac(n,d,max_denominator):

    #give a representation of n/d as N/D where D<=max_denominator
    #from python 2.6 fractions.py
    #
    # reduce by gcd and only run algorithm if d>maxdenominator
    g, b = n, d
    while b:
        g, b = b, g%b
    n, d = n/g, d/g
    if d <= max_denominator:
        return (n,d)
    nn, dd = n, d
    p0, q0, p1, q1 = 0, 1, 1, 0
    while True:
        a = nn//dd
        q2 = q0+a*q1
        if q2 > max_denominator:
            break
        p0, q0, p1, q1 = p1, q1, p0+a*p1, q2
        nn, dd = dd, nn-a*dd

    k = (max_denominator-q0)//q1
    bound1 = (p0+k*p1, q0+k*q1)
    bound2 = (p1, q1)
    if abs(bound2[0]*d - bound2[1]*n) <= abs(bound1[0]*d - bound1[1]*n):
        return bound2
    else:
        return bound1
1
ответ дан 5 December 2019 в 05:13
поделиться

Это не всегда разложимо, с тех пор не все десятичные числа являются частями (например, PI или e).

Кроме того, необходимо окружить к некоторой длине десятичное число перед преобразованием.

0
ответ дан 5 December 2019 в 05:13
поделиться

1/. 3333333333 = 3, потому что 1/3 =.3333333333333, таким образом, безотносительно числа Вы добираетесь, делают это,

удвойте x = 1 / yourDecimal; интервал y = Математика. Перекройте (x);

и теперь Дисплей "1 /" + y

0
ответ дан 5 December 2019 в 05:13
поделиться

Это работает только в Excel-VBA, но, поскольку у вас есть тег "VBA", я предлагаю его. В Excel есть настраиваемый формат «дроби», к которому вы можете получить доступ через «Формат ячеек» (или ctrl-1, если хотите). Этот конкретный числовой формат специфичен для Excel и поэтому не работает с функцией VBA.Format. Он работает , но работает с формулой Excel TEXT (). (Это эквивалент VBA.Format в Excel. Доступ к нему можно получить следующим образом:

Sub Example()    
    MsgBox Excel.WorksheetFunction.Text(.3333,"# ?/?")
End Sub

Чтобы отобразить более одной цифры (Пример 5/12), просто увеличьте количество вопросительных знаков.

6
ответ дан 5 December 2019 в 05:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: