Conversions from bases 0-16, 2CP, BCD
parent
303094d6dc
commit
99f517d0ba
|
@ -0,0 +1,144 @@
|
|||
import 'dart:math';
|
||||
|
||||
String decimalToBase(int number, toBase) {
|
||||
//current base as integer
|
||||
String tmpBase = toBase.toUpperCase();
|
||||
if (tmpBase == "HEX") tmpBase = "16";
|
||||
|
||||
bool negative = number < 0;
|
||||
if (negative) number *= -1;
|
||||
|
||||
String res = "";
|
||||
switch (tmpBase) {
|
||||
case "BCD":
|
||||
String n = number.toString();
|
||||
for (int i = 0; i < n.length; i++) {
|
||||
String digit = decimalToBase(int.parse(n[i]), "2");
|
||||
int missingZeros = 4 - digit.length;
|
||||
for (int i = 0; i < missingZeros; i++) {
|
||||
digit = "0" + digit;
|
||||
}
|
||||
res += digit;
|
||||
}
|
||||
if (negative) res = "-" + res;
|
||||
break;
|
||||
case "2CP":
|
||||
String binary = decimalToBase(number, 2);
|
||||
bool gotOne = false;
|
||||
if (negative) {
|
||||
for (int i = 0; i < binary.length; i++) {
|
||||
if (gotOne) {
|
||||
if (binary[i] == "1")
|
||||
binary[i] == "0";
|
||||
else
|
||||
binary[i] == "1";
|
||||
} else {
|
||||
if (binary[i] == "1") gotOne = true;
|
||||
}
|
||||
}
|
||||
res = binary;
|
||||
} else {
|
||||
res = "0" + binary;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
int base = int.parse(tmpBase); //current base as integer
|
||||
List<int> digits = [];
|
||||
|
||||
while (number != 0) {
|
||||
digits.add(number % base);
|
||||
number = number ~/ base;
|
||||
}
|
||||
digits = digits.reversed.toList();
|
||||
|
||||
for (int i = 0; i < digits.length; i++) {
|
||||
if (digits[i] >= 10) {
|
||||
res += String.fromCharCode(digits[i] + 55);
|
||||
} else {
|
||||
res += digits[i].toString();
|
||||
}
|
||||
}
|
||||
if (negative) res = "-" + res;
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
String baseToDecimal(String number, String pBase) {
|
||||
bool negative = number.startsWith('-');
|
||||
if (negative) number = number.split('-')[1];
|
||||
|
||||
//current base as integer
|
||||
String tmpBase = pBase.toUpperCase();
|
||||
if (tmpBase == "HEX") tmpBase = "16";
|
||||
|
||||
String cBase = tmpBase;
|
||||
if (cBase == "BCD" || cBase == "2CP") cBase = "2";
|
||||
int controlBase = int.parse(cBase);
|
||||
|
||||
for (int i = 0; i < number.length; i++) {
|
||||
if (charToDigit(number, i) >= controlBase) {
|
||||
return "error-invalid-number-for-base";
|
||||
}
|
||||
}
|
||||
|
||||
String res = "";
|
||||
switch (tmpBase) {
|
||||
case "BCD":
|
||||
int missingZeros = (4 - number.length % 4) % 4;
|
||||
for (int i = 0; i < missingZeros; i++) number = "0" + number;
|
||||
|
||||
for (int i = 0; i < number.length; i += 4) {
|
||||
String n = number[i];
|
||||
n += number[i + 1];
|
||||
n += number[i + 2];
|
||||
n += number[i + 3];
|
||||
String n1 = baseToDecimal(n, "2");
|
||||
print(n1);
|
||||
if (int.parse(n1) > 9) return "error-bcd-greater-nine";
|
||||
res += n1;
|
||||
}
|
||||
break;
|
||||
case "2CP":
|
||||
if (negative) {
|
||||
return "error-negative-cp2";
|
||||
}
|
||||
|
||||
int dres = 0;
|
||||
number = number.split('').reversed.join('').toString();
|
||||
for (int i = 0; i < number.length; i++) {
|
||||
int add = int.parse(number[i]) * pow(2, i).toInt();
|
||||
if (i == number.length - 1) add *= -1;
|
||||
dres += add;
|
||||
}
|
||||
res = dres.toString();
|
||||
break;
|
||||
default:
|
||||
int base = int.parse(tmpBase);
|
||||
List<int> digits = [];
|
||||
|
||||
// Get the value in decimal of the current digit
|
||||
for (int i = 0; i < number.length; i++) {
|
||||
int digit = charToDigit(number, i);
|
||||
digits.add(digit);
|
||||
}
|
||||
|
||||
//Reverse the list
|
||||
digits = digits.reversed.toList();
|
||||
|
||||
int dres = 0;
|
||||
for (int i = 0; i < digits.length; i++) {
|
||||
dres += digits[i] * pow(base, i).toInt();
|
||||
}
|
||||
res = dres.toString();
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int charToDigit(String s, int i) {
|
||||
return isDigit(s, i) ? int.parse(s[i]) : s.codeUnitAt(i) - 55;
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/25872456/dart-what-is-the-fastest-way-to-check-if-a-particular-symbol-in-a-string-is-a-d
|
||||
bool isDigit(String s, int i) => (s.codeUnitAt(i) ^ 0x30) <= 9;
|
181
lib/main.dart
181
lib/main.dart
|
@ -1,4 +1,7 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:base_converter/calculations.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
|
@ -13,15 +16,6 @@ class MyApp extends StatelessWidget {
|
|||
return MaterialApp(
|
||||
title: 'Base Converter',
|
||||
theme: ThemeData(
|
||||
// This is the theme of your application.
|
||||
//
|
||||
// Try running your application with "flutter run". You'll see the
|
||||
// application has a blue toolbar. Then, without quitting the app, try
|
||||
// changing the primarySwatch below to Colors.green and then invoke
|
||||
// "hot reload" (press "r" in the console where you ran "flutter run",
|
||||
// or simply save your changes to "hot reload" in a Flutter IDE).
|
||||
// Notice that the counter didn't reset back to zero; the application
|
||||
// is not restarted.
|
||||
primarySwatch: Colors.blue,
|
||||
),
|
||||
home: const MyHomePage(),
|
||||
|
@ -37,9 +31,8 @@ class MyHomePage extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
String fromBase = "One";
|
||||
String toBase = "One";
|
||||
|
||||
String fromBase = "2", savedFromBase = "";
|
||||
String toBase = "10", savedToBase = "";
|
||||
String result = "";
|
||||
|
||||
late TextEditingController _controller;
|
||||
|
@ -53,7 +46,9 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
return GestureDetector(
|
||||
onTap: () => hidekbd,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("Base Converter"),
|
||||
actions: [
|
||||
|
@ -83,13 +78,14 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||
icon: const Icon(Icons.info_outline_rounded))
|
||||
],
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Container(
|
||||
body: Container(
|
||||
margin: const EdgeInsets.fromLTRB(24, 32, 24, 32),
|
||||
child: Column(children: [
|
||||
mainBody(),
|
||||
Expanded(
|
||||
child: Center(child: richText),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(24),
|
||||
child: Center(child: resultToRichText())),
|
||||
)
|
||||
]),
|
||||
),
|
||||
|
@ -110,11 +106,11 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||
TextField(
|
||||
controller: _controller,
|
||||
decoration: const InputDecoration(hintText: "Number "),
|
||||
keyboardType: TextInputType.phone,
|
||||
),
|
||||
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
baseSelector("From:", fromBase),
|
||||
baseSelector("To:", toBase)
|
||||
]),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [baseSelector("From:", 0), baseSelector("To:", 1)]),
|
||||
Row(children: [
|
||||
Expanded(
|
||||
child: TextButton(
|
||||
|
@ -131,13 +127,74 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||
);
|
||||
}
|
||||
|
||||
void calculate() {}
|
||||
void hidekbd() {
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
}
|
||||
|
||||
void decimalToBase() {}
|
||||
RichText resultToRichText() {
|
||||
switch (result) {
|
||||
case "error-negative-in-cp2":
|
||||
return errorString("Error: 2CP number can't have a negative sign");
|
||||
case "error-bcd-greater-nine":
|
||||
return errorString("Error: BCD can only code digits from 0 to 9");
|
||||
case "error-invalid-number-for-base":
|
||||
return errorString(
|
||||
"Error: a digit is greater than or equal to the base");
|
||||
case "":
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
text: '',
|
||||
style: DefaultTextStyle.of(context).style,
|
||||
children: const <TextSpan>[],
|
||||
),
|
||||
);
|
||||
default:
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
text: '',
|
||||
style: DefaultTextStyle.of(context).style,
|
||||
children: <TextSpan>[
|
||||
mainNumber(_controller.text),
|
||||
baseSubtitle("($savedFromBase)"),
|
||||
mainNumber(" = $result"),
|
||||
baseSubtitle("($savedToBase)"),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void baseToDecimal() {}
|
||||
RichText errorString(String content) {
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
text: '',
|
||||
style: DefaultTextStyle.of(context).style,
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: content,
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal,
|
||||
fontFamily: "Roboto")),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Container baseSelector(String labelText, String value) {
|
||||
TextSpan mainNumber(String text) {
|
||||
return TextSpan(
|
||||
text: text,
|
||||
style: const TextStyle(
|
||||
color: Colors.black, fontSize: 18, fontWeight: FontWeight.bold));
|
||||
}
|
||||
|
||||
TextSpan baseSubtitle(String text) {
|
||||
return TextSpan(
|
||||
text: text, style: const TextStyle(color: Colors.black, fontSize: 14));
|
||||
}
|
||||
|
||||
Container baseSelector(String labelText, int i) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.all(4),
|
||||
child: Row(
|
||||
|
@ -147,17 +204,10 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
dpb(value),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
DropdownButton dpb(String dropdownValue) {
|
||||
return DropdownButton<String>(
|
||||
value: dropdownValue,
|
||||
DropdownButton<String>(
|
||||
value: i == 0 ? fromBase : toBase,
|
||||
icon: const Icon(Icons.arrow_downward),
|
||||
iconSize: 24,
|
||||
iconSize: 16,
|
||||
elevation: 16,
|
||||
style: const TextStyle(color: Colors.deepPurple),
|
||||
underline: Container(
|
||||
|
@ -166,34 +216,55 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||
),
|
||||
onChanged: (String? newValue) {
|
||||
setState(() {
|
||||
dropdownValue = newValue!;
|
||||
if (i == 0) {
|
||||
fromBase = newValue!;
|
||||
} else if (i == 1) {
|
||||
toBase = newValue!;
|
||||
}
|
||||
});
|
||||
},
|
||||
items: <String>[
|
||||
'One',
|
||||
'Two',
|
||||
'Three',
|
||||
'Four',
|
||||
'Five',
|
||||
'Six',
|
||||
'Seven',
|
||||
'Eight',
|
||||
'Nine',
|
||||
'Ten',
|
||||
'Eleven',
|
||||
'Twelve',
|
||||
'Thirteen',
|
||||
'Fourteen',
|
||||
'Fifteen',
|
||||
'Hex',
|
||||
'BCD',
|
||||
'2\'s CP'
|
||||
].map<DropdownMenuItem<String>>((String value) {
|
||||
items: items.map<DropdownMenuItem<String>>((String value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value,
|
||||
child: Text(value),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<String> items = <String>[
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'10',
|
||||
'11',
|
||||
'12',
|
||||
'13',
|
||||
'14',
|
||||
'15',
|
||||
'Hex',
|
||||
'BCD',
|
||||
"2CP"
|
||||
];
|
||||
|
||||
void calculate() {
|
||||
setState(() {
|
||||
hidekbd();
|
||||
savedFromBase = fromBase;
|
||||
savedToBase = toBase;
|
||||
|
||||
String s = baseToDecimal(_controller.text.toUpperCase(), savedFromBase);
|
||||
if (!s.startsWith("error")) s = decimalToBase(int.parse(s), savedToBase);
|
||||
result = s;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue