( num: number | bigint, fractionalDigits?: number | string )
| 131 | |
| 132 | for (let i = roman.length - 1; i >= 0; i--) { |
| 133 | const currentValue = romanMap[roman[i]]; |
| 134 | if (currentValue === undefined) return [total, roman.slice(i)]; |
| 135 | |
| 136 | if (currentValue < prevValue) total -= currentValue; |
| 137 | else total += currentValue; |
| 138 | |
| 139 | prevValue = currentValue; |
| 140 | } |
| 141 | |
| 142 | return [total, '']; |
| 143 | } |
| 144 | |
| 145 | export function fromDigits( |
| 146 | s: string, |
| 147 | baseInput?: string | number |
| 148 | ): [result: number, rest: string] { |
| 149 | s = s.trim(); |
| 150 | if (s.length === 0) return [NaN, '']; |
| 151 | if (s.startsWith('+')) return fromDigits(s.slice(1), baseInput); |
| 152 | if (s.startsWith('-')) { |
| 153 | const [v, r] = fromDigits(s.slice(1), baseInput); |
| 154 | return [-v, r]; |
| 155 | } |
| 156 | let base = 10; |
| 157 | if (typeof baseInput === 'string') baseInput = baseInput.toLowerCase(); |
| 158 | if (s.startsWith('0x')) { |
| 159 | base = 16; |
| 160 | s = s.slice(2); |
| 161 | } else if (s.startsWith('0b')) { |
| 162 | base = 2; |
| 163 | s = s.slice(2); |
| 164 | } else if (baseInput === 'roman') { |
| 165 | return fromRoman(s); |
| 166 | } else if (baseInput === 'base64' || baseInput === 'base-64') { |
| 167 | try { |
| 168 | return [parseInt(btoa(s)), '']; |
| 169 | } catch { |
| 170 | return [NaN, '']; |
| 171 | } |
| 172 | } else if (typeof baseInput === 'number') { |
| 173 | base = baseInput; |
no test coverage detected