Conversions from bases 0-16, 2CP, BCD

mobile
EmaMaker 2021-09-27 10:33:06 +00:00
parent 303094d6dc
commit 99f517d0ba
2 changed files with 311 additions and 96 deletions

144
lib/calculations.dart Normal file
View File

@ -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;

View File

@ -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;
});
}
}