Сообщение об ошибке вызвано тем, что тип 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 на приведенный выше код. Удачи!
Как.333333333 не 1/3, Вы никогда не будете получать 1/3, но вместо этого 333333333/1000000000, если Вы не добавите некоторую умную логику "неокругления".
Вот решение для обработки чисел с периодическим десятичным представлением, которое я помню из школы.
Номер 0.abcdabcd... равняется abcd/9999. Так 0.23572357... равняется 2357/9999 точно. Просто возьмите это многие 9 с, поскольку Ваш шаблон длинен. 0.11111... равняется 1/9, 0.121212... равняется 12/99, и так далее. Так пробуют просто поиск шаблона и установку знаменателя к соответствующему числу. Конечно, необходимо остановиться после некоторых цифр, потому что Вы никогда не будете знать, повторяется ли шаблон навсегда или просто много раз. И Вы поразите погрешность округления в последней цифре, таким образом, Вам все еще будет нужна некоторая умная логика.
Google для "десятичного числа для фракционирования" и Вы получите приблизительно огромное количество результатов.
Мне действительно нравится этот, потому что это просто, имеет исходный код (в RPL, подобном Forth, ~25 строкам), и довольно быстро (это записано для работы 4-разрядного, ЦП на 4 МГц). В документах говорится:
В книге под названием Учебник по Алгебре G. Chrystal, 1-й выпуск в 1889, во Второй части, Главе 32, этот улучшенный алгоритм непрерывной дроби представлен и доказан. Нечетный для сообщения Chrystal говорит о нем, как будто это было древнее знание.
Этот сайт, кажется, имеет действительно хорошую реализацию этого в JavaScript.
Я умножился бы на 10000000 (или независимо от того, что Вы хотите в зависимости от точности), затем упростите получающуюся часть (т.е. n*10000000/10000000)
Можно приблизить его. По существу циклически повторяют через все числители и знаменатели, пока Вы не достигаете части, которая является близко к тому, что Вы хотите.
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);
}
}
Это медленно и алгоритм грубой силы, но необходимо в общих чертах понять.
В целом будет легче при нахождении повторяющейся части рационального числа. Если Вы не можете найти, что, Вам будет нелегко. Скажем, число, если 8.45735735735...
Ответ равняется 8 + 45/100 + 735/999/100 = 8 1523/3330.
Целое число равняется 8. Добавьте 45/100 - который является.45, часть перед повторяющейся частью.
Повторяющаяся часть является 735/999. В целом примите повторяющееся участие. Сделайте это числителем. Знаменатель 10^ (количество повторяющихся цифр) - 1.
Примите повторяющееся участие и сместите его соответствующее количество цифр. В этом случае, два, что означает, делятся на 100, таким образом, 735/999/100.
После того как Вы понимаете те части, Вам просто нужен некоторый код, который добавляет и уменьшает части с помощью самых больших простых дробей...
Подобный 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, и я могу скорректировать его.
Править: Извините за проваленную подсветку синтаксиса. Я не могу выяснить, почему это неправильно. Если кто-то знает, как я могу сделать его лучше, сообщите мне.
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
Это не всегда разложимо, с тех пор не все десятичные числа являются частями (например, PI или e).
Кроме того, необходимо окружить к некоторой длине десятичное число перед преобразованием.
1/. 3333333333 = 3, потому что 1/3 =.3333333333333, таким образом, безотносительно числа Вы добираетесь, делают это,
удвойте x = 1 / yourDecimal; интервал y = Математика. Перекройте (x);
и теперь Дисплей "1 /" + y
Это работает только в 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), просто увеличьте количество вопросительных знаков.