-2

I recompiled my graphing application for wear OS and something broke. The app displays a grid and a waveform, but the waveform is getting mis constructed. In wear, the grid is more coarse and this error is evident. I have shown the original code and a modified sequence below.

// scale Y coordinate. Input,  elevation in feet.
// Output, y position of elevation in screen coordinate

static float scaleY(double elevation) {
    double a, b, c, offsetFromTopFeet, pixelRange, feetRange, pixelsPerFoot,offsetFromTopPixels;

    // original coding
    a = maxY - elevation;              //point in terms of feet within vert scale.
    b = (bottom - top) / (maxY - minY);
    c = top + (float) (a * b);
    // return (float)c;

    // new coding
    offsetFromTopFeet = maxY - elevation;        // a
    pixelRange = bottom - top;
    feetRange = maxY - minY;
    pixelsPerFoot = pixelRange / feetRange;     // b
    offsetFromTopPixels = top + offsetFromTopFeet * pixelsPerFoot;

    return (float) offsetFromTopPixels;
}

The calculation of b in the original coding returns an integer result even though the variable is a double. This is what distorts the waveform. In the reconstructed code shown underneath the variable pixelsPerFoot is calculated correctly, and the graph displays correctly. I have used this routine in android application for numerous years and either I never noticed the problem, the finer grid covered it up, or something else?

My question is why does the b calculation return an integer, but the pixelsPerFoot return the correct type? Is this a programming error?

Turing85
  • 18,217
  • 7
  • 33
  • 58
user1644002
  • 3,211
  • 3
  • 19
  • 21
  • This isn't going to be answerable unless we know the data type of every variable you're using. It could be something other than what you think it is. – Robert Harvey Dec 26 '19 at 15:33
  • Some comments on your code: Please refrain from declaring multiple variables in one line. Rather, declare each variable on its own line. --- Declare variables close to their first use, initialze them in declaration. --- Use speaking variable names: instead of `a`, `b`, `c`... use names that describe the semantics of this variable. – Turing85 Dec 26 '19 at 15:36
  • maxY, minY, bottom, and top are ints. – user1644002 Dec 26 '19 at 15:37
  • @user1644002 and why should the expression `(bottom - top) / (maxY - minY)` evaluate to a `double` or `float` then if all components are `int`s? – Turing85 Dec 26 '19 at 15:39
  • yes, the original code is from an example and I left it alone. and it is hard to understand. the replacement code i named variables with meaningful names. but that shouldn't matter to the compiler. – user1644002 Dec 26 '19 at 15:40
  • Turing, because b is a double. if I calculate a double variable as for example 3/2 the correct answer is 1.5 not .5 – user1644002 Dec 26 '19 at 15:42
  • You're not "calculating a double variable" - you are evaluating an entirely-integer expression *and then* assigning that integer result to a double-precision variable. –  Dec 26 '19 at 15:45
  • Well I guess to a java expert this is a dumb question. But I appreciate the answer I received before my question was closed. – user1644002 Dec 26 '19 at 18:31
  • And I still don't understand why I get endless warnings from Android Studio, such as "your variable name is misspelled" because it is not in their dictionary, and "your string should be placed in resources so it can be translated" when I have an English only application, but when the compiler assigns an int result to a double variable there is no warning. The language forces so much casting all the time that you could assume they take care with such things. If I did a calculation capable of producing a fraction, and wanted it as an integer, I would have cast it as such. Sloppy. – user1644002 Dec 26 '19 at 22:17

3 Answers3

2

The expression (bottom - top) / (maxY - minY); is of type int, since the subtraction of two ints is an int, and the division of an int by an int is also an int. The type of variable the result is assigned to is irrelevant; the calculation is performed using integer arithmetic and then converted to a floating point value after truncation.

Cast at least one of the variables to a floating point type, and the expression will be evaluated using a floating point division.

nanofarad
  • 40,330
  • 4
  • 86
  • 117
  • the compiler ignores the type of the destination, while doing a calculation? – user1644002 Dec 26 '19 at 15:51
  • 1
    @user1644002 the compiler doesn't do calculations – Michael Dec 26 '19 at 15:57
  • 1
    not trying to be argumentative, but it seems there are always tons of warnings about type mismatch, why not here? – user1644002 Dec 26 '19 at 16:00
  • @user1644002 because this isn't a type mismatch. The Java language specification defines the language in this way--whether it's good or bad is debatable but it's just a fact I take as a given. And yes, the type of an expression is based on the inputs and then converted to the output type if it matches--I personally would be more confused if the destination type affected the calculation. Worse yet, in new Java versions we don't specify types in all cases (`var` keyword) which would make more confusion if the destination type were important. – nanofarad Dec 26 '19 at 16:28
  • thank you for explaining – user1644002 Dec 26 '19 at 18:29
0

For this line of code:

b = (bottom - top) / (maxY - minY);

Where do bottom,top,maxY, andminY` come from? I don't see them defined in your posted code.

If they are integers, then of course b will end up with an integer value (stored in a double, but still integer). The left-hand side of an assignment doesn't change the numeric context of the right side. The right side is purely integer if all of the variables are integers.

If you do this:

b = (double) (bottom - top) / (maxY - minY);

That will give you the desired results.

kshetline
  • 12,547
  • 4
  • 37
  • 73
-1

all components being int you need a cast, for example (double) feetRange in denominator