Skip to content
This repository has been archived by the owner on Jul 11, 2019. It is now read-only.

Working with doubles as string is wrong #1

Open
avioli opened this issue Apr 6, 2018 · 0 comments
Open

Working with doubles as string is wrong #1

avioli opened this issue Apr 6, 2018 · 0 comments

Comments

@avioli
Copy link

avioli commented Apr 6, 2018

String decimal2sexagesimal(final double dec) {
List<int> _split(final double value) {
final List<String> tmp = round(value,decimals: 10).toString().split('.');
return <int>[ int.parse(tmp[0]).abs(), int.parse(tmp[1])];
}
final List<int> parts = _split(dec);
final int integerPart = parts[0];
final int fractionalPart = parts[1];
final int deg = integerPart;
final double min = double.parse("0.${fractionalPart}") * 60;
final List<int> minParts = _split(min);
final int minFractionalPart = minParts[1];
final double sec = (double.parse("0.${minFractionalPart}") * 60);
return "${deg}° ${min.floor()}' ${round(sec,decimals: 2).toStringAsFixed(2)}\"";
}

When dec is 53.0335 then splitting a double into two parts, that then get parsed as integers is wrong!

The fractionalPart 0335 becomes an integer - 335, and then "recreating" a double by doing 0.$fractionalPart is simply silly.

0.335 != 0.0335

final String sexa2 = decimal2sexagesimal(-42.883891);
expect(sexa2, '42° 53\' 02.01"'); // got '42° 53\' 20.08"'

The right way of doing this is:

/// Converts a decimal coordinate value to sexagesimal format
///
///     final String sexa1 = decimal2sexagesimal(51.519475);
///     expect(sexa1, '51° 31\' 10.11"');
///
///     final String sexa2 = decimal2sexagesimal(-42.883891);
///     expect(sexa2, '42° 53\' 02.01"');
///
String decimal2sexagesimal(final double dec) {
  if (dec == null) throw new ArgumentError.notNull('dec');

  final buf = new StringBuffer();

  final double absDec = dec.abs();
  final int deg = absDec.floor();
  buf.write(deg.toString() + '°');

  final double mins = (absDec - deg) * 60.0;
  final int min = mins.round();
  buf.write(' ' + zeroPad(min) + "'");

  final double secs = (mins - mins.floorToDouble()) * 60.0;
  final int sec = secs.round();
  final int frac = ((secs - secs.floorToDouble()) * 100.0).round();
  buf.write(' ' + zeroPad(sec) + '.' + zeroPad(frac) + '"');

  return buf.toString();
}

/// Pads a number with a single zero, if it is less than 10
String zeroPad(num number) => (number < 10 ? '0' : '') + number.toString();

Sorry, I'm calling this function a lot, so StringBuffer makes sense for me.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant